没有调用MarshalJSON

Iva*_*van 6 json marshalling go

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

func (m *RawMessage) MarshalJSON() ([]byte, error)
Run Code Online (Sandbox Code Playgroud)

我按照那个教程: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),
    })
}
Run Code Online (Sandbox Code Playgroud)

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

json.NewEncoder(w).Encode(EditionsMap)
Run Code Online (Sandbox Code Playgroud)

显然EditionsMapEditions结构的地图:

var EditionsMap map[string]datamodel.Edition
Run Code Online (Sandbox Code Playgroud)

问题是该MarshalJSON功能显然从未被调用过.

可能我做错了什么,但我无法理解问题是什么,我的理解是我只需要实现该功能以便调用它.

icz*_*cza 12

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

func (u *Edition) MarshalJSON() ([]byte, error)
Run Code Online (Sandbox Code Playgroud)

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

var EditionsMap map[string]datamodel.Edition
// ...
json.NewEncoder(w).Encode(EditionsMap)
Run Code Online (Sandbox Code Playgroud)

具有指针接收器的方法不是相应的非指针类型的方法集的一部分.类型的方法集datamodel.Edition 不包含该方法MarshalJSON().

规格:方法集:

类型可以具有与其关联的方法集.接口类型的方法集是其接口.任何其他类型的方法集T包含用接收器类型声明的所有方法T.设置相应的方法指针类型 *T是一组与接收器声明的所有方法*TT(即,它也包含的方法集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!
}
Run Code Online (Sandbox Code Playgroud)

指针类型的值*Edition 确实有一个方法MarshalJSON(),该方法将由json包正确调用.在Go Playground上尝试一个这方面的工作示例.

另一种选择是Edition.MarshalJSON()使用值接收器定义方法:

func (u Edition) MarshalJSON() ([]byte, error)
Run Code Online (Sandbox Code Playgroud)

这样,无论你是否编组指针或非指针值,它都会起作用,因为带有值接收器的方法是Edition类型和相应*Edition指针类型的方法集的一部分.在Go Playground上尝试这个变种的工作示例.