Reputation: 13868
I want to unmarshal
var j = []byte(`[{"major":1},{"minor":0}]`)
into
type Version struct {
Major int `json:"major"`
Minor int `json:"minor"`
}
using custom unmarshaler by looping the inner slice:
func (h *Version) UnmarshalJSON(b []byte) error {
var wrapper []json.RawMessage
err := json.Unmarshal(b, &wrapper)
if err == nil {
for _, v := range wrapper {
if err = json.Unmarshal(v, &h); err != nil {
break
}
}
}
return err
}
The inner UnmarshalJSON
triggers
json: cannot unmarshal object into Go value of type []json.RawMessage
which is strange because the target is a *Version
. What is wrong here? Play: https://play.golang.org/p/Av59IkYTioS
Upvotes: 2
Views: 11749
Reputation: 417402
The "inner" unmarshal call will recursively call Version.UnmarshalJSON()
:
json.Unmarshal(v, &h)
And your error comes from the recursive call: you try to unmarshal {"major":1}
into []json.RawMessage
.
You do not want to call Version.UnmarshalJSON()
recursively, so create a new type that strips all methods, including the UnmarshalJSON()
:
type version Version
h2 := (*version)(h)
for _, v := range wrapper {
if err = json.Unmarshal(v, &h2); err != nil {
break
}
}
With this change it works, and adding fmt.Println(msg)
the output will be (try it on the Go Playground):
<nil>
{1 0}
Normally this would cause a stack overflow error, but since your second call errors, the recursion breaks. See related: Call json.Unmarshal inside UnmarshalJSON function without causing stack overflow
Upvotes: 2