繁体   English   中英

GOLANG解组动态JSON

[英]GOLANG unmarshal dynamic JSON

我对 GOLANG 很陌生。

我已经尝试了很长一段时间来解组具有动态结构的以太坊 RPC JSON。 没有 GOLANG 结构和 map 设置我确实工作并且我能够获得 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>0x000000000000000000000000000000000000000000>balance>*>之类的值,这只是我尝试过的众多结构之一。 我无法在条目 0x00000000000000000000000000000000000000000 下得到任何东西


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)

Note that by default the encoding/json package can unmarshal a JSON string into a Go string , and it can unmarshal a JSON object into a Go map or a Go struct . 此外,它可以将任何 JSON 值解组到一个空的interface{}中。

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

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

但是因为 JSON 本身允许动态结构encoding/json package 提供了两个接口,使您能够自定义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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM