如何在Go中编组嵌入的结构体?

huangapple go评论73阅读模式
英文:

How to marshal an embedded struct in go?

问题

你想知道如何以正确的方式将整个JSON输出完全编组,而不需要通过所有字段进行迭代。

英文:

I've come across a case which is new to me in go. I think it is something similar to this question https://stackoverflow.com/questions/38489776/idiomatic-way-to-embed-struct-with-custom-marshaljson-method

Here is an example of code that I am trying to apply

main.go

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/ethereum/go-ethereum/ethclient"
)

func main() {

	icpPath, _ := os.LookupEnv("GETH_ICP_PATH")
	
    client, _ := ethclient.Dial(icpPath)
	ctx := context.Background()

	header, _ := client.HeaderByNumber(ctx, nil)
	data, _ := header.MarshalJSON()

	fmt.Println(string(data))

}

output

{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x400000000","number":"0x0","gasLimit":"0x1388","gasUsed":"0x0","timestamp":"0x0","extraData":"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000042","baseFeePerGas":null,"hash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}

In this output for example the field "difficulty" has a value of "0x400000000"

I can marshal this field like this:

difficulty, _ := header.Difficulty.MarshalJSON()
fmt.Println(string(difficulty))

and get the following output

17179869184

the type of header is as defined here
https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go

// Header represents a block header in the Ethereum blockchain.
type Header struct {
	ParentHash  common.Hash    `json:"parentHash"       gencodec:"required"`
	UncleHash   common.Hash    `json:"sha3Uncles"       gencodec:"required"`
	Coinbase    common.Address `json:"miner"            gencodec:"required"`
	Root        common.Hash    `json:"stateRoot"        gencodec:"required"`
	TxHash      common.Hash    `json:"transactionsRoot" gencodec:"required"`
	ReceiptHash common.Hash    `json:"receiptsRoot"     gencodec:"required"`
	Bloom       Bloom          `json:"logsBloom"        gencodec:"required"`
	Difficulty  *big.Int       `json:"difficulty"       gencodec:"required"`
	Number      *big.Int       `json:"number"           gencodec:"required"`
	GasLimit    uint64         `json:"gasLimit"         gencodec:"required"`
	GasUsed     uint64         `json:"gasUsed"          gencodec:"required"`
	Time        uint64         `json:"timestamp"        gencodec:"required"`
	Extra       []byte         `json:"extraData"        gencodec:"required"`
	MixDigest   common.Hash    `json:"mixHash"`
	Nonce       BlockNonce     `json:"nonce"`

	// BaseFee was added by EIP-1559 and is ignored in legacy headers.
	BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
}

My question is:

What is the right way to get the json output completly marshaled without going in iterative way through all fields?

答案1

得分: 3

types.Header 类型在这里实现了一个自定义的 JSON 编组器 here,你可以看到它用 Difficulty *hexutil.Big 替换了 Difficulty *big.Int,这就是为什么你在 JSON 中得到了十六进制值。

要禁用自定义编组器,你可以使用 types.Header 声明一个新类型作为 类型定义,然后,在编组头部之前,将其转换为这个新类型。

h := types.Header{Difficulty: big.NewInt(17179869184)}

type MyHeader types.Header // 声明新类型
out, err := json.Marshal(MyHeader(h)) // 转换并编组

https://play.golang.org/p/8CtWWDeItbO

英文:

The types.Header type implements a custom json marshaler here, and as you can see it replaces Difficulty *big.Int with Difficulty *hexutil.Big which is why you get that hex value in the json.

To disable the custom marshaler you can declare a new type using types.Header as the type definition, and then, just before you marshal the header, you convert it to this new type.

h := types.Header{Difficulty: big.NewInt(17179869184)}

type MyHeader types.Header // declare new type
out, err := json.Marshal(MyHeader(h)) // convert & marshal

https://play.golang.org/p/8CtWWDeItbO

huangapple
  • 本文由 发表于 2021年10月19日 03:20:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/69621461.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定