未调用 MarshalJSON

MarshalJSON not called

我正在尝试使用界面自定义 MarshalJSON 的输出:

func (m *RawMessage) MarshalJSON() ([]byte, error)

我遵循了该教程:http://choly.ca/post/go-json-marshalling/

我的目的是删除用 true/false 替换其中一个字段(如果设置或未设置),所以我最终编写了该函数:

func (u *Edition) MarshalJSON() ([]byte, error) {
    var vaultValue bool
    vaultValue = true
    var onlineValue bool
    vaultValue = false
    fmt.Println("here")
    if u.Vault == nil {
        vaultValue = false
    }
    if u.Online == nil {
        onlineValue = false
    }
    type AliasEdition Edition
    return json.Marshal(&struct {
        Vault  bool `json:"vault,omitempty"`
        Online bool `json:"online,omitempty"`
        *AliasEdition
    }{
        Vault:        vaultValue,
        Online:       onlineValue,
        AliasEdition: (*Alias)(u),
    })
}

JSON 是使用以下指令从地图创建的:

json.NewEncoder(w).Encode(EditionsMap)

显然 EditionsMapEditions 结构的映射:

var EditionsMap map[string]datamodel.Edition

问题是 MarshalJSON 函数显然从未被调用过。

可能我做错了什么,但我不明白问题出在哪里,我的理解是我只需要实现该函数才能调用它。

这是因为您使用 指针 接收器声明了 Edition.MarshalJSON() 方法:

func (u *Edition) MarshalJSON() ([]byte, error)

并且您尝试编组非指针值(您的映射包含 datamodel.Edition 个值):

var EditionsMap map[string]datamodel.Edition
// ...
json.NewEncoder(w).Encode(EditionsMap)

带有指针接收者的方法不属于相应非指针类型的方法集。类型datamodel.Edition的方法集不包含方法MarshalJSON().

Spec: Method sets:

A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

尝试整理指针值,定义您的映射以包含指针:

var EditionsMap map[string]*datamodel.Edition
// ...
if err := json.NewEncoder(w).Encode(EditionsMap); err != nil {
    panic(err) // HANDLE error somehow, do not omit it like in your example!
}

指针类型 *Edition 的值 确实有 方法 MarshalJSON() 将被 json 包正确调用。在 Go Playground.

上尝试一个工作示例

另一种选择是使用值 receiver:

定义 Edition.MarshalJSON() 方法
func (u Edition) MarshalJSON() ([]byte, error)

并且无论您编组指针值还是非指针值,这种方式都可以工作,因为具有值接收者的方法是 Edition 类型和相应 [=24] 类型方法集的一部分=] 指针类型。在 Go Playground.

上尝试此变体的工作示例