-
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: drop Options argument from user-declared methods and functions #71611
Comments
What if someone wants to explicitly ignore some option? This way there is no way to do so |
It seems to me that this would be equivalent to: func (v T) MarshalJSONTo(enc *jsontext.Encoder) error {
return json.MarshalEncode(enc, v.v, json.DefaultOptionsV2())
} I struggle to imagine a valid use-case, but at least it's possible. |
Related Issues Related Discussions (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
That also makes me think that there is no
Probably some edge-cases, like a need for |
Suppose there were a
Overriding select options is fairly reasonable, but to completely replace all options seems a bit odd. |
Oh right, i thought that that would be the only way to override options, but actually it would not work. To override, people should:
Yep. |
wrote about this also in parent issue and I think the custom Methods should not be in control on whether to honor an option or not. |
As one specific data point, I looked at places I've been using go-json-experiment and found at least one place that erroneously did not pass down the Options value when it should have, so definitely +1 for having a less error-prone API in this respect. |
WARNING: This commit contains breaking changes. This drops Options as an argument from the MarshalerTo and UnmarshalerFrom interfaces and the MarshalToFunc and UnmarshalFromFunc functions. Instead, the options is stored within the jsontext.Encoder or jsontext.Decoder and can be retrieved through the Options method. This simplifies the API for custom marshalers and unmarshalers and makes it impossible to accidentally drop the options when recursively calling json.MarshalEncode or json.UnmarshalDecode from within a custom marshaler or unmarshaler implementation. Fixes golang/go#71611
Proposal Details
This is a sub-issue of the "encoding/json/v2" proposal (#71497).
Here, we discuss whether to:
json.Options
argument fromjson.MarshalerTo
,json.UnmarshalerFrom
,json.MarshalToFunc
, andjson.UnmarshalFromFunc
.Options
accessor method tojsontext.Encoder
andjsontext.Decoder
.Specifically, this issue would result in the following changes to the API:
Functionally, we are dropping options as a direct argument and instead relying on the provided
jsontext.Encoder
orjsontext.Decoder
being capable of storing and retrieving options, where these options are able to represent both semantic options (i.e., options declared in the "json" package) and syntactic options (i.e., options declared in the "jsontext" package). This embraces the possibility thatEncoder
andDecoder
(which are functionally only concerned with the syntactic processing of JSON) are capable of storing semantic options (even if they have no relevance for syntactic processing).As a side-effect of this change, previously the passing of semantic options to
jsontext.NewEncoder
,jsontext.Encoder.Reset
,jsontext.NewDecoder
, orjsontext.Decoder.Reset
would have no effect and be ignored. Now, such options are stored within theEncoder
orDecoder
and while they continue to have no effect on the synctactic processing of JSON, they do take effect if theEncoder
orDecoder
is then passed tojson.MarshalEncode
orjson.UnmarshalDecode
.Analysis of this change:
✔️ This simplifies the implementation of author-defined marshalers and unmarshalers methods.
✔️ This makes it impossible to accidentally drop the options in recursive plumbing.
Currently, it is possible to write the following buggy code:
However, by dropping the
Options
argument, passing theenc
alone is sufficiently to properly plumb down the options.✔️ This assists in migration of v1 code. For example:
can be more directly re-written as:
where the options do not need to be repeatedly passed in to every
UnmarshalDecode
call.❌ This makes it easier for type authors to forget about the existence of options. However, usually authors know to look into the options if there an option that is semantically relevant to the operation at hand.
❌ Consulting the options is now an extra level of indirection.
In an older protype of
jsontext
, options were specified using option structs:By virtue of being a concrete
EncoderOptions
type, this constructor could only ever contain syntactic options. In fact, it would have been difficult to combinejsontext.EncoderOptions
andjson.MarshalOptions
since that would have resulted in cyclic dependency.By switching to variadic options represented by a Go interface, we made it possible to pass semantic options to the
Encoder
and the implementation is able to store it since it does not need to introspect upon the contents of the semantic options. From the perspective of theEncoder
it is just storing some opaque options and returning them back to the user. The loss of type purity is arguably an artifact of the decision to pursue variadic options and the proposed changed is a logical extension (or stronger embrace) of that approach.Overall, the benefits seem to outweigh the detriments and I believe we should pursue this change.
In this sub-issue, please refrain from off-topic discussions such as:
jsontext
intojsonv2
. This sub-issue assumes that the packages are split apart.Thank you @willfaught for suggesting this change.
The text was updated successfully, but these errors were encountered: