json unmarshal embedded struct

14,761

Solution 1

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

Solution 2

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

Share:
14,761
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I would like to unmarshal to struct Outer defined as:

    type Outer struct {
        Inner
        Num int
    }
    
    type Inner struct {
        Data string
    }
    func (i *Inner) UnmarshalJSON(data []byte) error {
        i.Data = string(data)
        return nil
    }
    

    Using json.Unmarshal(data, &Outer{}) seems only to use Inner's UnmarshalJSON and ignores the Num field: https://play.golang.org/p/WUBfzpheMl

    I have an unwieldy solution where I set the Num field manually, but I was wondering if anybody had a cleaner or simpler way to do it.

    Thanks!

  • Admin
    Admin over 7 years
    Thanks for the explanation!
  • Eric Chen
    Eric Chen about 5 years
    Sure, this solves the problem of not unmarshaling Num, however, it doesn't work with embedded data such as {"data": "test", "num": 1}, it would only work with something like {"inner": {"data": "test"}, "num": 1}.
  • Taku
    Taku over 4 years
    But Num is still 0, even though it should be 4
  • Mykola M.
    Mykola M. over 4 years
    Hmm, yes we can remove InnerRaw struct and UnmarshallJSON function. Result: play.golang.org/p/JkKCLQOnsHp and it works fine
  • Taku
    Taku over 4 years
    The OP wants to parse Num when there is UnmarshalJSON for Inner. If we remove UnmarshalJSON, then it wouldn't answer the question
  • Mohammad
    Mohammad over 4 years
    Agreed with Eric. I think this answer is only barely applicable in this case but in general case it's misleading.
  • maulik13
    maulik13 about 4 years
    This is a misleading answer. I understand that the question itself is a bit unclear, but the proposed solution has nothing to do with embedded type.