如何 json 在 Go 中使用自定义属性类型解组
How to json unmarshalling with custom attribute type in Go
在我的项目中,我定义了结构以便从 JSON 获取数据。
我尝试使用 json.Unmarshal()
函数。但它不适用于自定义类型属性。
曾经有这样的结构:
type TestModel struct {
ID NullInt `json:"id"`
Name string `json:"name"`
}
在那里,NullInt
类型定义为 MarshalJSON()
和 UnmarshalJSON()
函数的实现:
// NullInt ...
type NullInt struct {
Int int
Valid bool
}
// MarshalJSON ...
func (ni NullInt) MarshalJSON() ([]byte, error) {
if !ni.Valid {
return []byte("null"), nil
}
return json.Marshal(ni.Int)
}
// UnmarshalJSON ...
func (ni NullInt) UnmarshalJSON(b []byte) error {
fmt.Println("UnmarshalJSON...")
err := json.Unmarshal(b, &ni.Int)
ni.Valid = (err == nil)
fmt.Println("NullInt:", ni)
return err
}
在main()
函数中,我实现了:
func main() {
model := new(TestModel)
JSON := `{
"id": 1,
"name": "model"
}`
json.Unmarshal([]byte(JSON), &model)
fmt.Println("model.ID:", model.ID)
}
在控制台中,我得到:
UnmarshalJSON...
NullInt: {1 true}
model.ID: {0 false}
如您所见,NullInt.UnmarshalJSON()
被调用,ni
是我所期望的,但 model.ID
的值。
实现UnmarshalJSON()
功能的正确方法是什么?
此外,当我设置:JSON := `{"name": "model"}`
(没有id
)时,控制台只是:
model.ID: {0 false}
也就是说,UnmarshalJSON()
函数没有被调用,所以我没有以正确的方式得到 model.ID
的值。
UnmarshalJSON()
需要修改receiver,所以必须使用指针receiver:
func (ni *NullInt) UnmarshalJSON(b []byte) error {
// ...
}
receiver和所有的参数都是拷贝,如果不使用指针,只能修改一个拷贝,方法执行一次就会丢弃returns。如果你使用一个指针接收器,那也只是一个副本,但指向的值将是相同的,因此你可以修改原始(指向的)对象。
为了保持一致性,其他方法也使用指针接收器。
通过此更改,它可以工作并输出(在 Go Playground 上尝试):
UnmarshalJSON...
NullInt: &{1 true}
model.ID: {1 true}
在我的项目中,我定义了结构以便从 JSON 获取数据。
我尝试使用 json.Unmarshal()
函数。但它不适用于自定义类型属性。
曾经有这样的结构:
type TestModel struct {
ID NullInt `json:"id"`
Name string `json:"name"`
}
在那里,NullInt
类型定义为 MarshalJSON()
和 UnmarshalJSON()
函数的实现:
// NullInt ...
type NullInt struct {
Int int
Valid bool
}
// MarshalJSON ...
func (ni NullInt) MarshalJSON() ([]byte, error) {
if !ni.Valid {
return []byte("null"), nil
}
return json.Marshal(ni.Int)
}
// UnmarshalJSON ...
func (ni NullInt) UnmarshalJSON(b []byte) error {
fmt.Println("UnmarshalJSON...")
err := json.Unmarshal(b, &ni.Int)
ni.Valid = (err == nil)
fmt.Println("NullInt:", ni)
return err
}
在main()
函数中,我实现了:
func main() {
model := new(TestModel)
JSON := `{
"id": 1,
"name": "model"
}`
json.Unmarshal([]byte(JSON), &model)
fmt.Println("model.ID:", model.ID)
}
在控制台中,我得到:
UnmarshalJSON...
NullInt: {1 true}
model.ID: {0 false}
如您所见,NullInt.UnmarshalJSON()
被调用,ni
是我所期望的,但 model.ID
的值。
实现UnmarshalJSON()
功能的正确方法是什么?
此外,当我设置:JSON := `{"name": "model"}`
(没有id
)时,控制台只是:
model.ID: {0 false}
也就是说,UnmarshalJSON()
函数没有被调用,所以我没有以正确的方式得到 model.ID
的值。
UnmarshalJSON()
需要修改receiver,所以必须使用指针receiver:
func (ni *NullInt) UnmarshalJSON(b []byte) error {
// ...
}
receiver和所有的参数都是拷贝,如果不使用指针,只能修改一个拷贝,方法执行一次就会丢弃returns。如果你使用一个指针接收器,那也只是一个副本,但指向的值将是相同的,因此你可以修改原始(指向的)对象。
为了保持一致性,其他方法也使用指针接收器。
通过此更改,它可以工作并输出(在 Go Playground 上尝试):
UnmarshalJSON...
NullInt: &{1 true}
model.ID: {1 true}