GOLANG对动态JSON进行解组

  • 本文关键字:JSON 动态 GOLANG json go
  • 更新时间 :
  • 英文 :


我对GOLANG很陌生。

很长一段时间以来,我一直在尝试解组一个具有动态结构的以太坊RPCJSON。我没有工作过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>0x0000000000000000000000000000000000000000>平衡>>来自下面的结构只是我尝试过的众多结构之一。我无法获取条目0x00000000000000000000000000000000以下的任何内容


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"`
}

编辑:umarshal 代码

retObj := rpcCall(jstring)
var callResponse res_trace_replayTransaction
err := json.Unmarshal(retObj, &callResponse)
请注意,默认情况下,encoding/json包可以将JSON字符串解组为Gostring,也可以将JSON对象解组为Gomap或Gostruct。此外,它还可以将任何JSON值解组为空的interface{}

还要注意的是,Go是一种静态类型的语言,如果您指定一个值的类型为T1,那么在运行时,您就不能将其类型更改为T2。没有办法做到这一点,也没有办法更改值的类型。

因此,如果您将字段定义为某种struct类型,则默认情况下无法将JSON字符串解组到其中。同样,如果您定义字段为string类型,则在默认情况下也无法将JSON对象解组到中。

但由于JSON本身允许动态结构,encoding/json包提供了两个接口,使您能够自定义JSON的封送和取消封送方式。

因此,如果您有一个JSON属性(例如"balance""nonce"(,它可以是"="(字符串(或{ ... }(对象(,则需要声明一个实现json.Marshalerjson.Unmarshaler接口的自定义类型,这些接口知道如何正确封送和解组JSON值。

例如:

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用于避免对MarshalJSONUnmarshalJSON方法的无限递归调用导致的堆栈溢出

https://go.dev/play/p/yfsTrMozZ2Z

最新更新