鉴于以下结构
type Foo struct {
Thing time.Duration `json:"thing"`
}
type Bar struct {
Foo
Entry time.Duration `json:"entry"`
}
我想自定义
time.Duration
格式并从json字符串加载Bar
值,例如:{
"thing": "hour",
"entry": "second"
}
因此,我为
UnmarshalJSON
和Foo
(https://play.golang.org/p/6v71eG_Xr98)覆盖了Bar
:package main
import (
"encoding/json"
"fmt"
"time"
)
type Foo struct {
Thing time.Duration `json:"thing"`
}
type Bar struct {
Foo
Entry time.Duration `json:"entry"`
}
func timeConvert(s string) time.Duration {
if s == "hour" {
return time.Hour
}
if s == "second" {
return time.Second
}
return time.Duration(0)
}
func (t *Foo) UnmarshalJSON(data []byte) error {
type Alias Foo
a := struct {
Thing string `json:"thing"`
*Alias
}{Alias: (*Alias)(t)}
err := json.Unmarshal(data, &a)
t.Thing = timeConvert(a.Thing)
fmt.Printf("Foo: %v [%v]\n", *t, err)
return err
}
func (t *Bar) UnmarshalJSON(data []byte) error {
type Alias Bar
a := struct {
Entry string `json:"entry"`
*Alias
}{Alias: (*Alias)(t)}
err := json.Unmarshal(data, &a)
t.Entry = timeConvert(a.Entry)
fmt.Printf("Bar: %v [%v]\n", *t, err)
return err
}
func main() {
data := []byte(`{"entry": "second", "thing": "hour"}`)
json.Unmarshal(data, &Bar{})
}
但是它输出意外:
Foo: {1h0m0s} [<nil>]
Bar: {{1h0m0s} 0s} [<nil>]
为什么
Entry
值不正确? 最佳答案
感谢mkopriva。我发现这是因为'json.Unmarshal'适用于任何类型,它提示我所有类型均已实现'UnmarshalJSON'函数,但事实并非如此。
在“Bar”上调用“json.Unmarshal”实际上将执行以下操作:
UnmarshalJSON
上调用Bar
。 Bar
中的匿名结构未实现UnmarshalJSON
,所以在其上调用UnmarshalJSON
会嵌入结构Foo
。 这就是为什么匿名结构中的“条目”不会被解码的原因。
mkopriva建议使用自定义类型来获取自定义解析,但是当您需要将其作为
time
包中函数的参数传递时,这样做很不方便。我想出了另一种方法(只需解码两次,请参阅https://play.golang.org/p/2ahDX-0hsRt):func (t *Bar) UnmarshalJSON(data []byte) error {
type Alias Bar
if err := json.Unmarshal(data, (*Alias)(t)); err != nil {
return err
}
var tmp struct {
Entry string `json:"entry"`
}
err := json.Unmarshal(data, &tmp)
t.Entry = timeConvert(tmp.Entry)
fmt.Printf("Bar: %v [%v]\n", *t, err)
return err
}