当前位置: 首页 > 面试题库 >

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

羊舌勇
2023-03-14
问题内容

为了与大摇大摆进行交互,我需要制作一个自定义BigInt结构,该结构只不过是围绕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)
}

我希望SpendTx.JSON()最终会打来电话big.Int.MarshalJSON(),会回来0。相反,我得到了以下输出:

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

但是我真正想要的是:

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

而且我必须添加以下代码BigInt来做到这一点:

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

但是,根据Effective
Go的关于嵌入结构的部分
,这根本没有必要。为什么big.Int显示为{}


问题答案:

big.Int实现自定义JSON
marshaler(json.Marshaler),请参见Int.MarshalJSON()。但是此方法具有指针接收器,因此只有在具有指针值:时,才使用/调用该方法*big.Int

并且您嵌入了一个非指针值,因此不会调用此自定义封送拆收器,并且由于big.Int它是具有未导出字段的结构,因此您将在输出中看到一个空的JSON对象:{}

为了使其工作,您应该使用指向您的类型的指针,例如:

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

使用它的示例:

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

然后以输出为例(在Go Playground上尝试):

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

另一个选择是使用non-pointer utils.BigInt,但是utils.BigInt应该嵌入一个指针类型:

type BigInt struct {
    *big.Int
}

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

然后使用它:

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)

再次输出(在Go Playground上尝试):

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


 类似资料:
  • 问题内容: 考虑以下代码: 排序调用给出错误: 绑定不匹配:类型为Collections的通用方法sort(List )不适用于参数(ArrayList >)。推断的类型MyItem 不是有效替代边界参数<T扩展Comparable <?超级T>> 为什么会这样呢? 如果实施该工具,那为什么不能替代呢? 抱歉,是否有人提出这个问题,但我觉得这个问题有些具体。 问题答案: 实际上,对该错误的更详细说

  • 问题内容: 我正在尝试解组具有嵌入式类型的结构。当嵌入式类型具有UnmarshalJSON方法时,外部类型的解封将失败: https://play.golang.org/p/Y_Tt5O8A1Q 输出为: …因此两个自定义解组函数都运行了。来自嵌入式结构的值是正确的,但是来自外部结构的值将丢失。 如果我们只是删除EmbeddedStruct.UnmarshalJSON方法,它将按预期工作。 难道我

  • 问题内容: 我有以下几种类型: 我可以使用use ,但是我 不能 使用 似乎可以嵌入语法,但是使用它无效吗? 问题答案: 嵌入式类型是(未命名的)字段,由不合格的类型名称引用。 规格:结构类型: 使用类型但没有显式字段名称声明的字段是 匿名字段 ,也称为 嵌入式 字段或该类型在结构中的嵌入。必须将嵌入式类型指定为类型名称或指向非接口类型名称的指针,并且本身不能为指针类型。 非限定类型名称充当字段名

  • 我在许多组件中使用了几个大型对象,因此我为每个大型对象创建了一个proptypes文件,如下所示: 其中包含从"prop类型"导入PropType; 我在组件中使用对象,如下所示: 它给我一个警告,Prop类型“PropLargeObject”无效,它必须是一个函数,通常来自React。道具类型。我做错了什么?

  • 我正在尝试用来自spring WebFlux的WebClient制作一个客户端库。 服务器返回如下JSON所示的响应: 结果字段包含元素数组,这些元素可以根据使用的API而不同。 有关该API的更多信息,请参阅ServiceNow产品中的表API。 正如您在文档中所看到的,API路径如下所示:GET/now/table/{tableName},其中tableName可以是不同的值,tipology

  • 为什么Java可以推断出多个上限类型的共同祖先,而不能推断出下限类型的共同祖先? 更具体地说,请考虑以下示例: