繁体   English   中英

Unmarshal JSON与列表中的不同类型一起使用

[英]Unmarshal JSON in go with different types in a list

我无法解开JSON构造:

{
  "id": 10,
  "result": [
    {
      "bundled": true,
      "type": "RM-J1100"
    },
    [
      {
        "name": "PowerOff",
        "value": "AAAAAQAAAAEAAAAvAw=="
      },
      {
        "name": "Input",
        "value": "AAAAAQAAAAEAAAAlAw=="
      }
    ]
  ]
}

我实际上需要结果中的第二个切片项。

我目前的尝试是

type Codes struct {
    Id     int32      `json:"id"`
    Result []interface{} `json:"result"`
}

type ResultList struct {
    Info  InfoMap
    Codes []Code
}

type InfoMap struct {
    Bundled bool   `json:"bundled"`
    Type    string `json:"type"`
}

type Code struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

输出如下:

{10 {{false } []}}

但我也试过用这个:

type Codes struct {
    Id     int32      `json:"id"`
    Result []interface{} `json:"result"`
}

输出没问题:

{10 [map[type:RM-J1100 bundled:true] [map[name:PowerOff value:AAAAAQAAAAEAAAAvAw==] map[name:Input value:AAAAAQAAAAEAAAAlAw==]]]}

我也可以参考Result [1]索引:

[map[name:PowerOff value:AAAAAQAAAAEAAAAvAw==] map[name:Input value:AAAAAQAAAAEAAAAlAw==]]

但我无法将接口类型转换为任何其他匹配的类型。 任何人都可以告诉我如何进行界面转换。 什么方法将是“最好的”。

一种选择是最初将顶级事物解组成一片json.RawMessage

然后循环遍历成员,并查看每个成员的第一个字符。 如果它是一个对象,则将其解组到InfoMap头结构中,如果它是一个数组,则将其解组为Code结构的一个片段。

或者,如果它足够可预测,只需将第一个成员解组到一个结构,第二个成员解组到一个切片。

我做了一个这种方法的游乐场示例

type Response struct {
    ID        int               `json:"id"`
    RawResult []json.RawMessage `json:"result"`
    Header    *Header           `json:"-"`
    Values    []*Value          `json:"-"`
}

type Header struct {
    Bundled bool   `json:"bundled"`
    Type    string `json:"type"`
}

type Value struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

func main() {
    //error checks ommitted
    resp := &Response{}
    json.Unmarshal(rawJ, resp)
    resp.Header = &Header{}
    json.Unmarshal(resp.RawResult[0], resp.Header)
    resp.Values = []*Value{}
    json.Unmarshal(resp.RawResult[1], &resp.Values)
}

(我不会指出它是多么可怕这个JSON结构,但一如既往:sXXt发生)

您可以使用JSON Marshal / Unmarshal循环来转换您的结构。 代码如下:

package main

import (
    "encoding/json"
    "log"
)

const (
    inputJSON = `{
  "id": 10,
  "result": [
    {
      "bundled": true,
      "type": "RM-J1100"
    },
    [
      {
        "name": "PowerOff",
        "value": "AAAAAQAAAAEAAAAvAw=="
      },
      {
        "name": "Input",
        "value": "AAAAAQAAAAEAAAAlAw=="
      }
    ]
  ]
}`
)

type Codes struct {
    Id     int32          `json:"id"`
    Result [2]interface{} `json:"result"`
}

type Result struct {
    Info  InfoMap
    Codes []Code
}

type InfoMap struct {
    Bundled bool   `json:"bundled"`
    Type    string `json:"type"`
}

type Code struct {
    Name  string `json:"name"`
    Value string `json:"value"`
}

func main() {
    newCodes := &Codes{}
    err := json.Unmarshal([]byte(inputJSON), newCodes)
    if err != nil {
        log.Fatal(err)
    }

    // Prints the whole object
    log.Println(newCodes)

    // Prints the Result array (!)
    log.Println(newCodes.Result)

    if len(newCodes.Result) != 2 {
        log.Fatal("Invalid Result struct")
    }

    // Marshal and Unmarshal data to obtain the code list
    byteCodeList, _ := json.Marshal(newCodes.Result[1])

    codeList := make([]Code, 0)

    err = json.Unmarshal(byteCodeList, &codeList)
    if err != nil {
        log.Fatal("Invalid Code list")
    }

    // Prints the codeList
    log.Println(codeList)
}

操场上测试它。

暂无
暂无

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

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