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

mei*_*rsd -1 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
}
Run Code Online (Sandbox Code Playgroud)

自定义类型定义了MarshalJSON和UnmarshalJSON函数,因此当我将自定义类型序列化为JSON时,我希望在序列化输出中获取值的字符串,而不是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
....
Run Code Online (Sandbox Code Playgroud)

产生

{"flavor":2,"Count":13}
{"flavor":"Strawberry","Count":13}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下我都期望第二次输出.
为什么传递struct值不会在成员上调用MarshalJSON,但它确实编码正确的JSON?

有关完整的工作代码,请参阅 https://play.golang.org/p/mOl1GHhgynf

Vol*_*ker 5

在您的代码Flavor没有 MarshalJSON方法,因为您*Flavor只定义了方法.

如果你想type Flavor有MarshalJSON方法,你必须定义它Flavor不是*Flavor.

  • @Leon哎呀,抱歉.&d属于*Desert类型,所以忘记最后的评论.原因可能是:如果值是可寻址的,Go允许您在值接收器上调用指针接收器方法.如果您调用json.Marshal(d),则将d的副本传递给json.Marshal,此副本包含Flavor的副本.这些副本往往不可寻址. (2认同)