-
Notifications
You must be signed in to change notification settings - Fork 18
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
confusion with WithUnmarshalers #33
Comments
For case 1, we currently document on
but we can make this more explicit elsewhere in the documentation. If this does get merged into the stdlib, one could imagine a The downside of case 2 is that we would need to return an error in more cases where we take in The downside of case 3 is that it complicates what |
Looks good, I guess (now - that I know - that seems obvious :-) |
I faced a similar issue. I read the documentation @dsnet, but I understood it to mean that an unmarshal function for a struct will override a previous one for the same struct, not that an UnmarshalFuncV2 for one struct (e.g., Would it be feasible for the options to merge those definitions smartly? This would be particularly useful for my use case, where users can add marshalers/unmarshalers dynamically. Incidentally, I had to implement the following workaround to manage dynamic addition of marshalers/unmarshalers:
Having such functionality built into the JSON library would greatly simplify managing marshalers/unmarshalers dynamically and avoid the need for custom configurations like mine. Additionally, the plural method names like |
@MarkRosemaker, you bring up a legitimate use case of wanting to merge marshalers. I've been thinking about this and I couldn't come up with a solution that is consistently good in all areas. For the sake of discussion below, I'll just talk about caller-specified marshalers, but this equally applies to unmarshalers. Today you can do: m1, _ := json.GetOption(opts, json.WithMarshalers)
opts = json.JoinOptions(opts, json.WithMarshalers(json.NewMarshalers(m1, m2))) This is the minimal code you need to merge m1 with m2 (instead of having m2 entirely delete the existence of m1). Let's suppose we make it such that opts = json.JoinOptions(opts, m2) but then this opens up a different problems:
For example, a call like: json.Marshal(v, opts, json.DefaultOptionsV1()) should entirely use v1 semantics (i.e., no caller-specified marshalers), but would now still use them since we lost the ability to replace any marshalers in It seems to me that the current semantics is more consistent and flexible. Merging is at least possible even if it's not the default behavior (and whether merging of marshalers should be default behavior is also debatable). |
As another idea, I considered a generic func WithMarshaler[T any](func(dec *jsontext.Decoder, val *Conf, opts json.Options) error) Options where each However, this approach also runs into problems:
Today's API approach is still more flexible because The downside of this flexibility are the issues that @elv-gilles and @MarkRosemaker are reporting. |
I wanted to install multiple unmarshalers and wrote the wrong code below:
This code returns with no error, but the first unmarshalers is ignored.
Instead, after navigating in the source code of
json-experiment
, I discovered I should have written:Looking at the code, I also see that options are merged through
*Struct.Join
.I think it's currently easy to be tripped and (at least) one of the below - in order of increased preference - would be of interest:
UnmarshalDecode
orOptions
to prominently say that only the last option of a given kind will be used (if that comment exists I missed it), and/or*Struct.Join
return an error in case where an option would overwrite a previously set one, and/or*Struct.Join
handle such case and do whatNewUnmarshalers
does (for marshalers/unmarshalers)The text was updated successfully, but these errors were encountered: