GOLANG 解组动态 JSON
Posted
技术标签:
【中文标题】GOLANG 解组动态 JSON【英文标题】:GOLANG unmarshal dynamic JSON 【发布时间】:2022-01-21 01:55:22 【问题描述】:我是 GOLANG 的新手。
我已经尝试了很长一段时间来解组具有动态结构的以太坊 RPC JSON。我没有工作过 GOLANG 结构和映射设置,我能够获得 stateDiff 条目(3),但所有较低的结构似乎都没有填充任何数据。所以我能够遍历所有 3 个条目,但不知道如何访问下面的值,并且在转储解组结果时,我看到 GOLANG 并没有将数据传递到 StateDiff
JSON 文件:
"jsonrpc":"2.0",
"id":1,
"result":
"output":"0x0000000000000000000000000000000000000000000000000000000000000001",
"stateDiff":
"0x0000000000000000000000000000000000000000":
"balance":
"*":
"from":"0x45acecdfadb71366cf",
"to":"0x45aced3909536ccacf"
,
"code":"=",
"nonce":"=",
"storage":
,
"0x07865c6e87b9f70255377e024ace6630c1eaa37f":
"balance":"=",
"code":"=",
"nonce":"=",
"storage":
"0x86a60af761556602732bbdeaef13ba6e2481f83362d3489389f51353d86a6ac3":
"*":
"from":"0x0000000000000000000000000000000000000000000000000000000000000000",
"to":"0x0000000000000000000000000000000000000000000000000000000000002710"
,
"0xb0cf6f3c0836765b9dee3d1537458f10fe99447508adc172c1f633ac7352aaa8":
"*":
"from":"0x00000000000000000000000000000000000000000000000000092f379a04d2b0",
"to":"0x00000000000000000000000000000000000000000000000000092f379a04aba0"
,
"0x6dbe810e3314546009bd6e1b29f9031211cda5d2":
"balance":
"*":
"from":"0x41c41fc2c0247860",
"to":"0x41c3c66723c4155c"
,
"code":"=",
"nonce":
"*":
"from":"0x741",
"to":"0x742"
,
"storage":
,
"trace":[
],
"vmTrace":null
我试图将 JSON 解组为以下结构(在许多结构中),但我无法从 result>stateDiff>0x00000000000000000000000000000000000000000>balance>*>from 获取值 下面的结构只是我尝试过的众多之一。我在 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 任何任何东西下面的任何东西
type structChange struct
Changes map[string]string `json:"*"`
type structStateDiff struct
Balance *structChange `json:"balance"`
Code string `json:"code"`
Nonce string `json:"nonce"`
Storage map[string]*structChange `json:"storage"`
type res_trace_replayTransaction struct
Jsonrpc string `json:"jsonrpc"`
ID int `json:"id"`
Result struct
Output string `json:"output"`
StateDiff map[string]*structStateDiff `json:"stateDiff"`
Trace []interface `json:"trace"`
VMTrace interface `json:"vmTrace"`
`json:"result"`
编辑: 元帅代码
retObj := rpcCall(jstring)
var callResponse res_trace_replayTransaction
err := json.Unmarshal(retObj, &callResponse)
【问题讨论】:
请阅读 Go 教程:go.dev/doc/tutorial/getting-started,然后阅读 Go Json 教程,例如 gobyexample.com/json,我强烈建议不要匿名。而是为每个结构定义***type
s,然后在包含它的结构中使用类型名称。
已阅读,但我无法解决此问题。
然后再仔细阅读一下 json 示例。前 3 段中的一段告诉您您做错了什么:“只有导出的字段才会在 JSON 中编码/解码。字段必须以大写字母开头才能导出。”
"我没有工作过的 GOLANG 结构和地图设置" 我会为此使用 struct
s - 不是匿名的,而是命名的结构类型 - 但你不需要需要使用struct
s。您也可以执行go.dev/play/p/P4ryK-9wuVl 之类的操作 - 缺点是您必须自己进行所有类型检查,这就是 struct
s 更好的原因
另外你没有包含你的解组代码
【参考方案1】:
请注意,默认情况下,encoding/json
包可以将 JSON 字符串解组为 Go string
,它可以将 JSON 对象解组为 Go map
或 Go struct
。此外,它可以将任何 JSON 值解组为空的 interface
。
另请注意,Go 是一种静态类型的语言,如果您指定一个值为T1
类型,那么在运行时,您无法将其类型更改为T2
。没有办法做到这一点,没有办法改变一个值的类型。
因此,如果您将某个字段定义为某种 struct
类型,则默认情况下,您无法将 JSON 字符串解组到其中。同样,如果您将字段定义为 string
类型,默认情况下,您无法将 JSON 对象解组到其中。
但由于 JSON 本身允许动态结构,encoding/json
包提供了两个接口,使您能够自定义 JSON 的格式为 marshaled 和 unmarshaled。
因此,如果您有一个 JSON 属性(例如 "balance"
或 "nonce"
),可以是 "="
(字符串)或 ...
(对象),您需要声明一个自定义类型实现了知道如何正确编组和解组 JSON 值的 json.Marshaler
和 json.Unmarshaler
接口。
例如:
type structChange struct
Changes map[string]string `json:"*"`
func (s structChange) MarshalJSON() ([]byte, error)
// if empty retrun `"="`
if len(s.Changes) == 0
return []byte(`"="`), nil
// otherwise marshal as is
type T structChange
return json.Marshal(T(s))
func (s *structChange) UnmarshalJSON(data []byte) error
// if `"="`, ignore
if string(data) == `"="`
return nil
// otherwise assume it's a valid object
type T structChange
return json.Unmarshal(data, (*T)(s))
注意:上面的临时类型T
用于避免无限递归调用MarshalJSON
和UnmarshalJSON
方法引起的堆栈溢出。
https://go.dev/play/p/yfsTrMozZ2Z
【讨论】:
所以问题在于平衡的“”字段。我现在已经删除了它并且它可以工作,不幸的是这不是解决方案。如何解组“”键域? @ThomasMiller 我不明白你在说什么。请使用新代码更新您的问题,并清楚地解释您现在面临的问题/错误。 @ThomasMiller 通常你需要做一个零检查,例如if x != nil ...
,表示您想要使用的任何x
,但在使用它的上下文中可能是nil
。如果没有看到实际代码和恐慌的完整堆栈跟踪,就不可能更具体。如果您需要更多帮助,您需要使用新信息更新问题。或者打开一个新问题。
非常感谢。我现在实际上找到了这个解决方案并看到了您的回复。我在结构中检查了太高的 nil 而不是实际重要的最低字段。现在,我抓住了 nil 的情况,它不会抛出错误以上是关于GOLANG 解组动态 JSON的主要内容,如果未能解决你的问题,请参考以下文章
在 Golang 中解组 XML 时如何在 interface 中获取数据?