Go提供encoding/json.Unmarshaler
接口,因此类型可以控制它们从JSON解码的方式。几乎在所有情况下,编码的JSON值都直接传递给UnmarshalJSON
方法,但如果Unmarshaler
是指针且JSON值为null
则不会。在这种情况下,指针设置为nil
而根本不调用UnmarshalJSON
。这是一个例子:
package main
import (
"encoding/json"
"fmt"
)
type T string
func (v *T) UnmarshalJSON(b []byte) error {
if b[0] == 'n' {
*v = "null"
} else {
*v = "not null"
}
return nil
}
func main() {
var a struct {
T T
PT1 *T
PT2 *T
}
a.PT1 = nil // just to be explicit
a.PT2 = new(T)
err := json.Unmarshal([]byte(`{"T":null,"PT1":"foo","PT2":null}`), &a)
if err != nil {
panic(err)
}
fmt.Printf("a.T is %#v\n", a.T)
if a.PT1 == nil {
fmt.Println("a.PT1 is nil")
} else {
fmt.Printf("a.PT1 points to %#v\n", *a.PT1)
}
if a.PT2 == nil {
fmt.Println("a.PT2 is nil")
} else {
fmt.Printf("a.PT2 points to %#v\n", *a.PT2)
}
}
我希望打印
a.T is "null"
a.PT1 points to "not null"
a.PT2 points to "null"
相反,它打印
a.T is "null"
a.PT1 points to "not null"
a.PT2 is nil
因此json.Unmarshal
为T
分配了一个新的a.PT1
,最初为nil
。但是,即使a.PT2
不是nil
,它也会UnmarshalJSON
设置为a.PT2
而不会调用nil
。为什么呢?
答案 0 :(得分:1)
这是因为将指针设置为nil
是处理JSON null
的最常用方法,UnmarshalJSON
方法无法*T
这样做。如果在这种情况下调用UnmarshalJSON
,您必须定义(**T).UnmarshalJSON
以将*T
设置为nil
。这将使最常见的情况非常尴尬。
如果您不希望JSON null
成为Go nil
,请不要使用指针。