Skip to content

encoding/json: cannot call UnmarshalJSON on value receiver through interface #27722

Open
@dsnet

Description

@dsnet

Noticed this inconsistency when poking around the code:

type CustomUnmarshaler struct{ p *bytes.Buffer }

func (cu CustomUnmarshaler) UnmarshalJSON(b []byte) error {
	cu.p.Write(b)
	return nil
}
func (cu CustomUnmarshaler) String() string {
	return fmt.Sprintf("custom %v", cu.p.String())
}

func main() {
	s := &struct {
		F1 CustomUnmarshaler
		F2 interface{}
		F3 interface{}
	}{
		CustomUnmarshaler{new(bytes.Buffer)},
		CustomUnmarshaler{new(bytes.Buffer)},
		&CustomUnmarshaler{new(bytes.Buffer)},
	}
	json.Unmarshal([]byte(`{"F1": "F1", "F2": "F2", "F3": "F3"}`), s)
	fmt.Println(s.F1)
	fmt.Println(s.F2)
	fmt.Println(s.F3)
}

This current prints:

custom "F1"
F2
custom "F3"

I expect it to print:

custom "F1"
custom "F2"
custom "F3"

In this case, UnmarshalJSON is a method on the value receiver. This is a rare situation for methods that mutate the receiver, but is valid. I expect the method to still be called. That is, the json package should not assume that the receiver must be a pointer.

This is a very obscure use-case and I personally don't have a horse in the game to address this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions