如何在UnmarshalJSON中调用json.Unmarshal而不引起堆栈溢出?
问题描述:
How can I create a method UnmarshalJSON inside a struct, use json.Unmarshal inside without causing stack overflow?
package xapo
type Xapo struct {}
func (x Xapo) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, &x)
if err != nil {
return err
}
fmt.Println("done!")
return nil
}
Can someone explain me why the stack overflow happens? Can it be fixed?
Thanks in advance.
答
It looks like you may be trying to do custom unmarshaling by using the default unmarshaler and then post-processing the data. However, as you've discovered, the obvious way of trying this causes an infinite loop!
The usual workaround is to create a new type using your type, use the default unmarshaler on an instance of the new type, post-process the data, and then finally cast to the original type and assign back to the target instance. Note that you'll want to implement UnmarshalJSON on a pointer type.
For example:
func (x *Xapo) UnmarshalJSON(data []byte) error {
// Create a new type from the target type to avoid recursion.
type Xapo2 Xapo
// Unmarshal into an instance of the new type.
var x2 Xapo2
err := json.Unmarshal(data, &x2)
if err != nil {
return err
}
// Perform post-processing here.
// TODO
// Cast the new type instance to the original type and assign.
*x = Xapo(x2)
return nil
}