为什么编码JSON结构成员不调用自定义MarshalJSON?

时间:2018-10-09 13:41:38

标签: json go

在Golang中,我有一个结构,其成员是具有常量值的自定义int类型。基本上,自定义类型是一个逻辑枚举。

type Flavor int

const (
    Vanilla Flavor = iota
    Chocolate
    Strawberry
)

func (f *Flavor) MarshalJSON() ([]byte, error) {
    return []byte(strconv.Quote(f.String())), nil
}

自定义类型定义了MarshalJSON和UnmarshalJSON函数,因此当我将自定义类型序列化为JSON时,我希望在序列化输出中获得值的 string ,而不是int值。

我的问题是,如果我有一个指向包含类型的指针,那么包含类型将使用自定义函数封送,但如果尝试仅使用结构值封送,则JSON包不会调用自定义MarshalJSON

type Dessert struct {
    Flavor Flavor `json:"flavor"`
    Count  int
}
....
    d := Dessert{Strawberry, 13}

    b, err = json.Marshal(d) // !! does not invoke members Marshal !!
    b, err = json.Marshal(&d) // works as expected
....

产生

{"flavor":2,"Count":13}
{"flavor":"Strawberry","Count":13}

两种情况下我都希望有第二个输出。
为什么传递struct值时不会在成员上调用MarshalJSON而是对正确的JSON进行编码?

请参见https://play.golang.org/p/mOl1GHhgynf 以获得完整的工作代码

2 个答案:

答案 0 :(得分:5)

在您的代码Flavor中,没有没有MarshalJSON方法,因为您仅为*Flavor定义了方法。

如果您希望type Flavor具有MarshalJSON方法,则必须在Flavor而不是*Flavor上定义它。

答案 1 :(得分:-1)

哦,呵呵。我想您有Volker和Leon。我以为MarshalJSON需要一个指针接收器,因为UnmarshalJSON肯定需要一个指针接收器。但是

func (f Flavor) MarshalJSON() ([]byte, error) {
...
func (f *Flavor) UnmarshalJSON(b []byte) error {
...

混合接收器会导致json.Marshal(d) json.Marshal(&d)

的预期输出