Как демаршировать JSON с массивом структур ключ-значение, где ключ не имеет тега json - PullRequest
0 голосов
/ 08 февраля 2020

У меня проблемы с отменой вызова следующего json:

{
    "input-1": [
        "S",
        15.0,
        "some1",        
        [
            [
                1111111.357,
                "QQ",
                "Toronto"
            ]
        ]
    ],
    "input-2": [
        "EE",
        90.1,
        "some2",
        [
            [
                55555550.705,
                "RR",
                "Kuala Lumpur"
            ],
            [
                22233330.134,
                "OO",
                "Bogota"
            ]           
        ]
    ],
    "input-3": [
        "UU",
        87.0,
        "some99",       
        [
            [
                8800221.500,
                "LL",
                "Lagos"
            ]
        ]
    ]
}

Мой соответствующий код выглядит так:

package main

import (
    "fmt"
    "encoding/json"
    "os"
    "io/ioutil"
)

type InputC struct {
    Type                string
    SomeFloat           float64
    CorrespondingPerson string
    Desc                []Under
}
type Under struct {
    IDCity   float64
    CityType string
    CityName string
}
func main() {
    f, err := os.OpenFile("data.json", os.O_RDONLY, 0755)
    if err != nil {
        fmt.Printf("Error opening file: %v\n", err)
    }

    b, err := ioutil.ReadAll(f)
    if err != nil {
        fmt.Printf("Error reading file: %v\n", err)
    }

    inputs:= map[string]InputC{}
    err = json.Unmarshal(b, &inputs)
    if err != nil {
        fmt.Printf("Error Unmarshalling file: %v\n", err)
    }

    for k, v := range(inputs) {
        fmt.Printf("%v\n",v.Desc[0].IDCIty)
    }
}

Ответ, который я получаю от этого кода: :

Ошибка файла демаршаллинга: json: не удается распаковать массив в Go значение типа main.Input C pani c: ошибка времени выполнения: индекс выходит за пределы диапазона

После чего я изменил свой код на это:

    inputs:= []InputC{}

, но все еще получаю ошибку:

Ошибка Unmarshalling file: json: не удается разархивировать объект в Go значение типа [] main.Input C

Совершенно очевидно, что мне чего-то не хватает, но я не могу понять, как извлечь информацию из JSON, которая у меня есть.

1 Ответ

1 голос
/ 08 февраля 2020

Вы можете избежать необходимости использовать []interface{}, если реализуете интерфейс json.Unmarshaler в своих пользовательских структурах и используете []json.RawMessage для временного хранения значений отдельных элементов массива. Имейте в виду, что приведенное ниже решение в значительной степени зависит от количества и порядка значений массива, которые должны быть гарантированы.

type InputC struct {
    Type                string
    SomeFloat           float64
    CorrespondingPerson string
    Desc                []Under
}

func (c *InputC) UnmarshalJSON(data []byte) error {
    var s []json.RawMessage
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    if len(s) != 4 {
        return errors.New("something's off")
    }

    dest := []interface{}{&c.Type, &c.SomeFloat, &c.CorrespondingPerson, &c.Desc}
    for i := 0; i < len(s); i++ {
        if err := json.Unmarshal(s[i], dest[i]); err != nil {
            return err
        }
    }
    return nil
}

type Under struct {
    IDCity   float64
    CityType string
    CityName string
}

func (u *Under) UnmarshalJSON(data []byte) error {
    var s []json.RawMessage
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    if len(s) != 3 {
        return errors.New("something's off")
    }

    dest := []interface{}{&u.IDCity, &u.CityType, &u.CityName}
    for i := 0; i < len(s); i++ {
        if err := json.Unmarshal(s[i], dest[i]); err != nil {
            return err
        }
    }
    return nil
}

https://play.golang.com/p/qpnvETC18rp

(Обратите внимание, что с плавающей точкой, напечатанные на игровой площадке только выглядят иначе, потому что именно так пакет fmt печатает плавающие по умолчанию при использовании глагола %v. Например, fmt.Printf("%v", 1111111.357) выводит 1.111111357e+06.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...