简体   繁体   English

GOLANG解组动态JSON

[英]GOLANG unmarshal dynamic JSON

I am very new to GOLANG.我对 GOLANG 很陌生。

I have been trying for quite some time now to unmarshal an ethereum RPC JSON which has a dynamic structure.我已经尝试了很长一段时间来解组具有动态结构的以太坊 RPC JSON。 No GOLANG struct and map setup I did worked and I am able to get the stateDiff entries (3) but all lower structs seem not to be filled ith any data.没有 GOLANG 结构和 map 设置我确实工作并且我能够获得 stateDiff 条目(3)但所有较低的结构似乎都没有填充任何数据。 So I am able to loop through all the 3 entries but then don't know how to access the values below and when dumping the unmarshal result, I see that GOLANG is not delivering the data anyway into StateDiff所以我能够遍历所有 3 个条目,但不知道如何访问下面的值,并且在转储解组结果时,我看到 GOLANG 并没有将数据传递到 StateDiff

JSON FILE: 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
   }
}

I have tried to unmarshal the JSON into the following structure (among many) and i can't get the values such as result>stateDiff>0x0000000000000000000000000000000000000000>balance>*>from Struct below is just one of many i tried.我试图将 JSON 解组为以下结构(在许多结构中),但我无法从下面的结构中获取诸如result>stateDiff>0x000000000000000000000000000000000000000000>balance>*>之类的值,这只是我尝试过的众多结构之一。 I can't get anything below the entry 0x0000000000000000000000000000000000000000我无法在条目 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"`
}

EDIT: Code for umarshal编辑:元帅代码

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 . 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 . Additionally it can unmarshal any JSON value into an empty interface{} .此外,它可以将任何 JSON 值解组到一个空的interface{}中。

Also note that Go is a statically typed language, if you specify a value to be of type T1 then, at runtime, you cannot change it's type to T2 .另请注意, Go 是一种静态类型语言,如果您将值指定为T1类型,那么在运行时,您无法将其类型更改为T2 There is just no way to do it, no way to change a value's type.没有办法做到这一点,没有办法改变一个值的类型。

So if you define a field to be of some struct type, you cannot, by default, unmarshal a JSON string into it.因此,如果您将字段定义为某种struct类型,则默认情况下,您无法将 JSON 字符串解组到其中。 And equally if you define a field to be of type string , you cannot, by default, unmarshal a JSON object into it.同样,如果您将字段定义为string类型,默认情况下,您不能将 JSON object 解组到其中。

But because JSON itself allows for a dynamic structure the encoding/json package provides two interfaces that give you the ability to customize how the JSON is marshaled and unmarshaled .但是因为 JSON 本身允许动态结构encoding/json package 提供了两个接口,使您能够自定义JSON如何编组和解组。

So if you have a JSON property (eg "balance" or "nonce" ) that can be either "=" (a string), or {... } (an object), you will need to declare a custom type that implements the json.Marshaler and json.Unmarshaler interfaces that know how to properly marshal and unmarshal the JSON value.因此,如果您有一个 JSON 属性(例如"balance""nonce" )可以是"=" (字符串)或{... } (对象),您将需要声明一个实现的自定义类型json.Marshalerjson.Unmarshaler接口知道如何正确编组和解组 JSON 值。

For example:例如:

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))
}

NOTE: the temporary type T above is used to avoid a stack overflow caused by an infinite recursive call to the MarshalJSON and UnmarshalJSON methods.注意:上面的临时类型T用于避免无限递归调用MarshalJSONUnmarshalJSON方法导致的堆栈溢出。

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

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

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