dongliang9682 2016-08-26 10:47
浏览 81
已采纳

没有调用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条回答

  • drbd65446 2016-08-26 11:08
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝