-
-
Notifications
You must be signed in to change notification settings - Fork 27
Add support for omitempty field tag to exclude empty values from queries and headers
#107
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
Conversation
…eries and headers
|
Build is failing due to rate limiting in CodeCov - will try a rebuild later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update!
README.md
Outdated
| Page int `in:"query=page;default=1"` | ||
| PerPage int `in:"query=per_page;default=20"` | ||
| IsMember bool `in:"query=is_member"` | ||
| Search *string `in:"query=search,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query directive is designed in the signautre as query(name1, name2, ...), here the omitempty will be read as the second name used in the query parameters. I'm thinking:
- if we should define a separate
omitemptydirective for this, i.e.in:"query=search;header=x-api-keyword;omitempty"? - shall we just use
patch.Field[T]as the field type, since it was designed for indicating absent values, i.e.Search patch.Field[string], whenSearch.Valid == false, it will be omitted from the final resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using patch.Field[T] for the field type would not be ideal for us as this would complicate using our library for consumers, if this can be handled purely by the stuct tags then this would be ideal.
I have updated it to use a new omitempty directive now. I do agree it is better.
I'm not sure on the implementation - as the new directive doesn't take any action by itself - but is used inside the existing directives - maybe this is ok, or maybe there is a better way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally agree. I hope patch.Field[T] should be used only in rare cases.
core/formencoder.go
Outdated
|
|
||
| func (e *FormEncoder) Execute(rtm *DirectiveRuntime) error { | ||
| tag := rtm.Resolver.Field.Tag.Get("in") | ||
| if rtm.Value.IsZero() && strings.Contains(tag, "omitempty") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is error prone. Either check
rtm.Directive.Argvforomitemptydefined in a directive, orrtm.Resolver.GetDirectiveforomitemptydefined as a single directive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! Have gone with option 2.
core/formencoder.go
Outdated
| func (e *FormEncoder) Execute(rtm *DirectiveRuntime) error { | ||
| if rtm.Value.IsZero() { | ||
| for _, d := range rtm.Resolver.Directives { | ||
| if d.Name == "omitempty" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we could use a constant here to link this back to the actual directive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's okay. But we can use API rtm.Resolver.GetDirective("omitempty") here to simplify the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! missed that.
| // DirectiveOmitEmpty is used with the DirectiveQuery, DirectiveForm, and DirectiveHeader to indicate that the field | ||
| // should be omitted when the value is empty. | ||
| // It does not have any affect when used by itself | ||
| type DirectiveOmitEmpty struct{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the json package, omitempty is a tag that affects both json marshalling and unmarshalling. Since we have modified the encoding behaviour of using omitempty here, I would suggest upgrading decoding as well to have the similar effects. Otherwise, it might bring up suprises for users who expect omitempty to work in the decoding function. Have you ever considered how it should behave in decoding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that omitempty only affects Marshal with json, and not Unmarshal - as such I think it only makes sense to only modify encoding and not decoding.
Or maybe I'm missing something obvious!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you're right. The omitempty tag only influences the marshalling process (i.e., converting a Go struct into JSON).
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #107 +/- ##
==========================================
- Coverage 90.78% 90.70% -0.08%
==========================================
Files 34 35 +1
Lines 1530 1539 +9
==========================================
+ Hits 1389 1396 +7
- Misses 97 99 +2
Partials 44 44
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Adds support for an
omitemptytag.Main use case is for query parameters where we may not want have empty keys
i.e.
/pets?name_pointer=By adding
omitemptyto the tag then this the key will not appear in the query stringi.e.
This will create
/petsThis has been added to the
formencoderso that it will also remove empty headers.I have picked
omitemptyas I feel this will feel most natural for engineers as they are likely already used to this syntax with JSON.