-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
proposal: encoding/json/v2: add support for user-defined format flags and option values #71664
Comments
Thanks for opening this. Just for the record, while I support use cases and proposal above, I would prefer if custom marshal implementation could access full struct tags for a field currently being marshaled instead of just format (it is OK if format is exposed through additional/special flag because it is the most common case). |
I'm not sure I understand why this is needed. Most of the field tag options are specific to the serialization of the parent Go struct and the child field type should not care. The current set of all proposed tag options are
|
The use case is that I could then do something like: type Person struct {
Name string `json:"name"`
Surname string `json:"surname"`
SSN string `json:"ssn,omitempty" private:""`
}
json.Marshal(Person{...},
json.WithMarshalers(json.JoinMarshalers(
json.MarshalToFunc(func(enc *jsontext.Encoder, _ string, opts json.Options) error {
if _, private := opts.Tag().Lookup("private"); private {
return enc.WriteToken(jsontext.String(""))
}
return json.SkipFunc
}),
)),
) Here I use (BTW, I support that options would simply be accessible through If in the future context could be accessible during marshaling, then I could make private fields conditioned on the current user or user's permissions. |
I see, I was under the impression, access to struct tags was for the JSON-specific tag options, but your goal is to access user-specific information in the tags (in general). It's an interesting idea. Technically, you could fold that information in the |
I like everything but the names. WithOption is odd because it's not the only func that returns an Option. The "With" parts are odd because they're not adding an option to an existing Options. |
Proposal Details
This is a sub-issue of the "encoding/json/v2" proposal (#71497).
Here we propose additional API to support user-defined format flags and option values.
This builds on top of the v2 API and does not block the acceptance of v2.
Example third-party package that supports custom formats:
Example usage of custom formats supported by the
geo
package:Example third-party package that supports custom options:
Example usage of custom options supported by the
protojson
package:Both
WithFormat
andWithOption
support some way for user-defined options to alter the representation of options.For now, we do not support interface types as it is unclear whether retrieval of an option (e.g.,
GetOption(opts, json.WithOption[MyType])
) should also check whether any options are set for other interface types thatMyType
also implements. Trying to construct an option of an interface type panics. In the future, this restriction can be lifted, but allows providing value sooner for a suspected majority of use cases.Alternatives considered
Instead of
WithOption
, we could consider makingjson.Option
an interface that could be implemented by any declared type (i.e., all exported methods). However, it is unclear how the "json" package would merge options together and how to retrieve the custom options type back out of a combinedjson.Options
. Also, this is more boilerplate for every user since they would need to implement at least one method to implementjson.Option
. The proposedWithValue
API avoids unnecessary boilerplate for the user and only requires that the user declare a type, but no extra machinery.An alternative API is to make the signature of
WithValue
similar tocontext.WithValue
which accepts a user-provided key and value. In order to prevent conflicts between keys, the API requires that the key be a user-defined type. However, if we are going to require that, why not just make the user-defined value type the key itself? If so, we're back to a solution similar to the currently proposedWithValue
API.The text was updated successfully, but these errors were encountered: