json unmarshal embedded struct
This is happening because Inner
is being embedded in Outer
. That means when json library calls unmarshaler on Outer
, it instead ends up calling it on Inner
.
Therefore, inside func (i *Inner) UnmarshalJSON(data []byte)
, the data
argument contains the entire json string, which you are then processing for Inner
only.
You can fix this by making Inner
explicit field in Outer
Outer struct {
I Inner // make Inner an explicit field
Num int `json:"Num"`
}
Working example
Just delete UnmarshalJSON
in your example because it's used in unmarshaling of Outer
since Inner
is inlined. Otherwise, you need to override it if you want to do something custom.
https://play.golang.org/p/D6V6vKpx9J
Faced same issue. One solution is to unmarshal twice for each sub structs. E.g.
type Inner struct {
Data string
}
type NumField struct {
Num int
}
type Outer struct {
Inner
NumField
}
func (i *Inner) UnmarshalJSON(data []byte) error {
i.Data = string(data)
return nil
}
func (o *Outer) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &o.Inner); err != nil {
return err
}
if err := json.Unmarshal(data, &o.NumField); err != nil {
return err
}
return nil
}
func main() {
x := Outer{}
data := []byte(`{"Num": 4}`)
_ = json.Unmarshal(data, &x)
fmt.Printf("%#v\n", x)
}
This requires moving the extra fields into a separate struct.