没有调用MarshalJSON

I'm trying to customize the output of MarshalJSON, using the interface:

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

I followed that tutorial: http://choly.ca/post/go-json-marshalling/

My purpose is removing replace one of the fields with true/false (if set or not), so I ended up writing that function:

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),
    })
}

The JSON is created from a map with the following instruction:

json.NewEncoder(w).Encode(EditionsMap)

Obviously EditionsMap is a Map of Editions structures:

var EditionsMap map[string]datamodel.Edition

The problem is that the MarshalJSON function apparently is never called.

Probably I'm doing something wrong, but I cannot understand what is the problem, my understanding is that I just need to implement that function in order to get it called.

1个回答

This is because you declared the Edition.MarshalJSON() method with pointer receiver:

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

And you try to marshal non-pointer values (your map contains datamodel.Edition values):

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

Methods with pointer receiver are not part of the method set of the corresponding non-pointer type. The method set of type datamodel.Edition does not contain the method 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).

Try to marshal pointer values, define your map to contain pointers:

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!
}

Values of the pointer type *Edition does have a method MarshalJSON() which will be called properly by the json package. Try a working example of this on the Go Playground.

Another option would be to define the Edition.MarshalJSON() method with value receiver:

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

And this way it would work no matter if you marshal pointer or non-pointer values, as the methods with value receiver are part of the method set of both the Edition type and the corresponding *Edition pointer type. Try a working example of this variant on the Go Playground.

douzai9405
douzai9405 如果您有一个值(非指针),则希望它的方法不会修改它(因为它“只是”一个值,而不是一个指针,并将其传递给它创建了副本)。 如果指针方法位于其方法集中,则它们可以对其进行修改,这可能会更加混乱(比不将指针接收器包含在其方法集中的方法)。
接近 3 年之前 回复
douliang9057
douliang9057 这是一个很好的答案。 我无法想象golang为什么这样做-似乎容易出错。 我和OP有同样的问题。
接近 3 年之前 回复
duancan65665
duancan65665 OMG,我发现了问题,它是在导入中我没有注意到,但是导入是在另一个我没有删除的软件包中更新了该文件的旧版本,因此我对其所做的任何更改都无法识别 通过应用程序。 感谢您的帮助,您帮助我更好地了解了MarshalJSON功能! :)
大约 4 年之前 回复
douou6696
douou6696 您确定代码执行到此为止吗? 插入日志消息。 另外Encoder.Encode()返回错误,请确保您检查(当前不检查,请参阅我的修改后的答案)。
大约 4 年之前 回复
drqvr26084
drqvr26084 谢谢您的帮助,但是我的代码仍然有问题。 在这里,您可以找到具有MarshalJSON和我正在使用的所有结构的源文件:github.com/inuyasha82/mtgrestservice/blob/marshaljson/datamodel / ...,我尝试在此处创建示例play.golang.org/p/Z6JlpH0qjN和 显然,它是可行的,因此在我的原始代码中应该有问题,但无法弄清楚什么:'(从未调用过MarshalJson。
大约 4 年之前 回复
douchui3933
douchui3933 参见编辑后的答案。 我为这两种情况编写了一个简短的示例,您可以在Go操场上查看它们(答案中的链接)。 是的,在您的MarshalJSON()方法中,您可以更改任何所需的内容,这实际上取决于您返回的内容(如何编组值)。 你有完全的自由。
大约 4 年之前 回复
dousi8237
dousi8237 嗨,icza,谢谢您的忙,显然我试图更改映射以包含指针,但是显然没有运气,我也试图更改声明没有指针的函数,显然没有运气! 嗯,还有一个问题,我可以在marshalJSON期间更改元素的类型吗? Vault和Online的原始结构具有* struct {}类型(它们来自xml,它们是空节点,例如:<vault />)
大约 4 年之前 回复
dpw70180
dpw70180 是的,已更正。
大约 4 年之前 回复
duanjia7607
duanjia7607 版本Map是否不是map [string]数据模型类型。版本?
大约 4 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐