dtbi27903 2019-03-25 12:33
浏览 76
已采纳

MarshalJSON具有嵌入式类型的类型最终以{}代替值

To interact with swagger, I needed to make a custom BigInt struct which does nothing more than wrap around go's big.Int.

type BigInt struct {
    big.Int
}

...
type SpendTx struct {
    SenderID    string       `json:"sender_id,omitempty"`
    RecipientID string       `json:"recipient_id,omitempty"`
    Amount      utils.BigInt `json:"amount,omitempty"`
    Fee         utils.BigInt `json:"fee,omitempty"`
    Payload     string       `json:"payload,omitempty"`
    TTL         uint64       `json:"ttl,omitempty"`
    Nonce       uint64       `json:"nonce,omitempty"`
}

func (t SpendTx) JSON() (output []byte, err error) {
    return json.Marshal(t)
}

I'd expect SpendTx.JSON() to eventually call big.Int.MarshalJSON(), which would return 0. Instead, I got this output:

{"sender_id":"alice","recipient_id":"bob","amount":{},"fee":{},"payload":"Hello World","ttl":10,"nonce":1}

But what I really want is this:

{"sender_id":"alice","recipient_id":"bob","amount":10,"fee":10,"payload":"Hello World","ttl":10,"nonce":1}

And I had to add this bit of code to BigInt to do it:

func (b BigInt) MarshalJSON() ([]byte, error) {
    return b.Int.MarshalJSON()
}

But according to Effective Go's section on embedding structs, this shouldn't be necessary at all. Why is big.Int appearing as as {}?

  • 写回答

1条回答 默认 最新

  • doufeng3602 2019-03-25 12:41
    关注

    big.Int implements a custom JSON marshaler (json.Marshaler), see Int.MarshalJSON(). But this method has pointer receiver, so it is only used / called, if you have a pointer value: *big.Int.

    And you embed a non-pointer value, so this custom marshaler is not called, and since big.Int is a struct with unexported fields, you will see an empty JSON object in the output: {}.

    To make it work, you should use a pointer to your type, e.g.:

    Amount      *utils.BigInt `json:"amount,omitempty"`
    Fee         *utils.BigInt `json:"fee,omitempty"`
    

    Example using it:

    s := SpendTx{
        SenderID:    "alice",
        RecipientID: "bob",
        Amount:      &utils.BigInt{},
        Fee:         &utils.BigInt{},
    }
    data, err := s.JSON()
    fmt.Println(string(data), err)
    

    Then output will be for example (try it on the Go Playground):

    {"sender_id":"alice","recipient_id":"bob","amount":0,"fee":0} <nil>
    

    Another option is to use the non-pointer utils.BigInt, but then utils.BigInt should embed a pointer type:

    type BigInt struct {
        *big.Int
    }
    
    type SpendTx struct {
        Amount      utils.BigInt `json:"amount,omitempty"`
        Fee         utils.BigInt `json:"fee,omitempty"`
    }
    

    And then using it:

    s := SpendTx{
        SenderID:    "alice",
        RecipientID: "bob",
        Amount:      utils.BigInt{new(big.Int)},
        Fee:         utils.BigInt{new(big.Int)},
    }
    data, err := s.JSON()
    fmt.Println(string(data), err)
    

    And output will be again (try it on the Go Playground):

    {"sender_id":"alice","recipient_id":"bob","amount":0,"fee":0} <nil>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 运筹学中在线排序的时间在线排序的在线LPT算法
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧