Skip to content

confusion with WithUnmarshalers #33

Open
@elv-gilles

Description

@elv-gilles

I wanted to install multiple unmarshalers and wrote the wrong code below:

	err := json.UnmarshalDecode(dec, c,
		json.WithUnmarshalers(
			json.UnmarshalFuncV2(func(dec *jsontext.Decoder, val *Conf, opts json.Options) error {
				// do something
				return json.SkipFunc
			})),
		json.WithUnmarshalers(
			json.UnmarshalFuncV2(func(dec *jsontext.Decoder, val *SubConf, opts json.Options) error {
				// do something
				return json.SkipFunc
			})))

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:

	err := json.UnmarshalDecode(dec, c,
		json.WithUnmarshalers(
			json.NewUnmarshalers(
				json.UnmarshalFuncV2(func(dec *jsontext.Decoder, val *Conf, opts json.Options) error {
					// do something
					return json.SkipFunc
				}),
				json.UnmarshalFuncV2(func(dec *jsontext.Decoder, val *SubConf, opts json.Options) error {
					// do something
					return json.SkipFunc
				}),
			)))

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:

  1. improve the comment of UnmarshalDecode or Options to prominently say that only the last option of a given kind will be used (if that comment exists I missed it), and/or
  2. have *Struct.Join return an error in case where an option would overwrite a previously set one, and/or
  3. have *Struct.Join handle such case and do what NewUnmarshalers does (for marshalers/unmarshalers)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions