自定义UnmarshalJSON:数组对象映射。

问题描述 投票:1回答:1

我有这样的json文件。

{
   "Systems":[
      {
         "ID":74,
         "Data1":0.1,
         "Data2":4
      },
      {
         "ID":50,
         "Data1":31,
         "Data2":3
      }
   ],
   "Error":false
}

我想在围棋中解密成这样(注意 map):

type Info struct {
    Systems map[int]System `json:"Systems"`  // key should be ID json field
    Error   bool           `json:"Error"`
}

type System struct {
    Data1 float32 `json:"Data1"`
    Data2 int     `json:"Data2"`
}

这是我的(错误的)代码:

package main

import (
    "encoding/json"
    "fmt"
)

type Info struct {
    Systems map[int]System `json:"Systems"` // key should be ID json field
    Error   bool           `json:"Error"`
}

type System struct {
    ID    int     `json:"ID"`
    Data1 float32 `json:"Data"`
    Data2 int     `json:"Data2"`
}

func main() {
    file := "{\"Systems\":[{\"ID\":74,\"Data1\":0.1,\"Data2\":4},{\"ID\":50,\"Data1\":31,\"Data2\":3}],\"Error\":true}"
    info := Info{}
    bytes := []byte(file)
    err := json.Unmarshal(bytes, &info)
    if err != nil {
        fmt.Printf("=> %v\n", err)
    }
    fmt.Printf("INFO: %+v\n", info)
}

func (d *Info) UnmarshalJSON(buf []byte) error {
    var tmp interface{}
    if err := json.Unmarshal(buf, &tmp); err != nil {
        return err
    }
    d.Error = tmp.(map[string]interface{})["Error"].(bool)
    d.Systems = make(map[int]System)
    for _, v := range tmp.(map[string]interface{})["Systems"].([]interface{}) {
        d.Systems[v.(map[string]interface{})["ID"].(int)] = v.(map[string]interface{}).(System)
    }
    return nil
}

https:/play.golang.orgpL_Gx-f9ycjW

json parsing go unmarshalling
1个回答
2
投票

你可以试试这个

package main

import (
    "encoding/json"
    "fmt"
)

func main() {

    var str = `{
        "Systems":[
        {
            "ID":74,
            "Data1":0.1,
            "Data2":4
        },
        {
            "ID":50,
            "Data1":31,
            "Data2":3
        }
        ],
        "Error":false
    }`

    var t Info
    err := json.Unmarshal([]byte(str), &t)
    if err != nil {
        panic(err)
    }

    bts, err := json.MarshalIndent(t, "", " ")
    if err != nil {
        panic(err)
    }

    fmt.Println(string(bts))

}

type Info struct {
    Systems map[int]System `json:"Systems"`
    Error   bool           `json:"Error"`
}

type System struct {
    ID    int     `json:"ID,omitempty"`
    Data1 float32 `json:"Data1"`
    Data2 int     `json:"Data2"`
}

func (info *Info) UnmarshalJSON(data []byte) error {

    var t struct {
        Systems []System `json:"Systems"`
        Error   bool     `json:"Error"`
    }

    err := json.Unmarshal(data, &t)
    if err != nil {
        return err
    }

    info.Systems = make(map[int]System, 0)

    for _, v := range t.Systems {
        info.Systems[v.ID] = v
    }

    return nil
}

https:/play.golang.orgpqB3vF08cmW8。

输出。

    {
    "Systems": {
        "50": {
            "ID": 50,
            "Data1": 31,
            "Data2": 3
        },
        "74": {
            "ID": 74,
            "Data1": 0.1,
            "Data2": 4
        }
    },
    "Error": false
}

0
投票

你不能直接在你提出的结构中解码json 因为它不符合json结构。

你可以做的是将json解码成这样。

type Info struct {
    Systems []*System `json:"Systems"`  // array here
    Error   bool     `json:"Error"`

    Index map[int]*System   // not json mapped
}

type System struct {
    ID    int     `json:"ID"`
    Data1 float32 `json:"Data1"`  
    Data2 int     `json:"Data2"`
}

然后将其填充到 Index 字段在后处理中使用类似这样的方法。

    var info Info
    json.Unmarshal(dataIn, &info)
    info.Index = map[int]*System{} // initialize an empty map
    for _, s := range info.Systems {
        info.Index[s.ID] = s
    }
    fmt.Println(info.Index[50].Data1)

你可以在这里找到一个完整的例子 https:/play.golang.orgpB8O6nfI258-。

© www.soinside.com 2019 - 2024. All rights reserved.