Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How should nullable query params be handled without pointers? #393

Open
wolveix opened this issue Apr 19, 2024 · 4 comments
Open

How should nullable query params be handled without pointers? #393

wolveix opened this issue Apr 19, 2024 · 4 comments
Labels
question Further information is requested

Comments

@wolveix
Copy link
Contributor

wolveix commented Apr 19, 2024

Hey! Excellent project, I've been reworking various projects to make use of Huma and have loved it (despite the initial learning curve).

We use a filter struct that gets passed through various layers, and use pointers for each field to support nullable and empty values. Unfortunately, Huma doesn't support pointers for query params. I thought I could just switch to checking if a value was empty, but then ran into the issue of booleans. How should this be approached without a hacky workaround? I did read the TODO in the codebase as to why pointers aren't currently supported :(

Thanks in advance!

@wolveix wolveix changed the title How to handle nullable query params How should nullable query params be handled without pointers? Apr 19, 2024
@danielgtaylor danielgtaylor added the question Further information is requested label Apr 20, 2024
@danielgtaylor
Copy link
Owner

@wolveix yes this is a little bit of an inconvenience until I can refactor some of the code to potentially support pointer parameters.

For now I suggest using meaningful zero values, so making it that false means no action is taken, same with numbers that are zero, empty string, time.Time.IsZero(), etc. If that's just not possible for some parameter, you can always load it manually using a resolver. Here's a quick example:

https://go.dev/play/p/S9h07SdH4Zr

The downside of using a resolver is you will need to manually document the parameter using e.g. api.OpenAPI().Paths["/your/path"].Get.Parameters....

@wolveix
Copy link
Contributor Author

wolveix commented Apr 22, 2024

Gotcha, thanks for the suggestions @danielgtaylor! What aspect of the code needs to be refactored to support it? I did have a brief look through, and would be happy to work on this myself if you wouldn't mind pointing out where specifically needs work :)

@danielgtaylor
Copy link
Owner

@wolveix unfortunately it's some of the most complex code in the project which glues together all the smaller pieces and takes the cached reflection info to parse and set values on structs. I just haven't had time to refactor / simplify this code.

The crux of the problem is that the callback to Every is called with a reflect.Value which in the non-pointer case is already an allocated piece of memory we can easily set. In the pointer case it is not, so it needs to be allocated only when needed and the value must be settable, otherwise you potentially need access to the parent. I'm not 100% sure anymore as it's been a while since I looked into this. Hope that helps, and don't feel bad abandoning this idea due to complexity and unfamiliarity with the codebase!

@wolveix
Copy link
Contributor Author

wolveix commented Apr 22, 2024

Understood, thank you for the detailed information! I can see why you put off refactoring it :)

The custom resolver route you suggested seems like it might work, so I'm going to play around with that a little bit. If not, I'll deep dive the codebase a bit to see whether I can figure out what needs to be refactored, and whether it makes sense for me to work on it or not.

Thanks again! Huma is such an excellent project :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants