Custom Unmarshal JSON: массив объектов для сопоставления - PullRequest
1 голос
/ 23 апреля 2020

У меня есть json такие файлы:

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

Я хотел бы распаковать в Go что-то вроде этого (примечание 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.org/p/L_Gx-f9ycjW

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Вы можете попробовать это

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.org/p/qB3vF08cmW8

Выход:

    {
    "Systems": {
        "50": {
            "ID": 50,
            "Data1": 31,
            "Data2": 3
        },
        "74": {
            "ID": 74,
            "Data1": 0.1,
            "Data2": 4
        }
    },
    "Error": false
}
0 голосов
/ 24 апреля 2020

Вы не можете декодировать 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.org/p/B8O6nfI258-

...