Unmarshal Несогласованный JSON в Go - PullRequest
0 голосов
/ 23 февраля 2019

Я работаю с JSON, который возвращает три разных типа объектов 'items', 'Categories' и 'modifiers'. Пример JSON можно посмотреть здесь. Я создал модели для трех типов объектов.Но когда я отменяю маршализацию, я выбрал один из типов, чтобы демонтировать весь JSON. (Я знаю, что это не может быть правильным способом ...) Затем я пытаюсь разобрать различные элементы в зависимости от того, какой их тип идентифицирован как вJSON поле «Тип», а затем добавить этот объект к фрагменту соответствующего типа.У меня возникают ошибки, потому что я не знаю, как демонтировать JSON с разными типами и полями.

Каков правильный способ демонтажа JSON, который содержит разные объекты, каждый из которых имеет свои соответствующие поля?

Является ли решение для создания "супер-модели", которая содержит все возможные поля и затем отменяет маршалинг?

Я все еще новичок и буду признателен за любые советы.Спасибо!

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Я думаю https://github.com/mitchellh/mapstructure также подходит для вашего случая использования.

0 голосов
/ 23 февраля 2019

Если вы реализуете json.Unmarshaler , вы можете определить структуру, которая будет анализировать каждый тип элемента в его соответствующую структуру.

Пример:

// Dynamic represents an item of any type.
type Dynamic struct {
    Value interface{}
}

// UnmarshalJSON is called by the json package when we ask it to
// parse something into Dynamic.
func (d *Dynamic) UnmarshalJSON(data []byte) error {
    // Parse only the "type" field first.
    var meta struct {
        Type string
    }
    if err := json.Unmarshal(data, &meta); err != nil {
        return err
    }

    // Determine which struct to unmarshal into according to "type".
    switch meta.Type {
    case "product":
        d.Value = &Product{}
    case "post":
        d.Value = &Post{}
    default:
        return fmt.Errorf("%q is an invalid item type", meta.Type)
    }

    return json.Unmarshal(data, d.Value)
}

// Product and Post are structs representing two different item types.
type Product struct {
    Name  string
    Price int
}

type Post struct {
    Title   string
    Content string
}

Использование:

func main() {
    // Parse a JSON item into Dynamic.
    input := `{
        "type": "product",
        "name": "iPhone",
        "price": 1000
    }`
    var dynamic Dynamic
    if err := json.Unmarshal([]byte(input), &dynamic); err != nil {
        log.Fatal(err)
    }

    // Type switch on dynamic.Value to get the parsed struct.
    // See https://tour.golang.org/methods/16
    switch dynamic.Value.(type) {
    case *Product:
        log.Println("got a product:", dynamic.Value)
    case *Post:
        log.Println("got a product:", dynamic.Value)
    }
}

Вывод:

2009/11/10 23:00:00 получил продукт: & {iPhone 1000}

Попробуйте это на игровой площадке Go .


Совет: если у вас есть список динамических объектов, просто разберите на фрагмент Dynamic:

var items []Dynamic
json.Unmarshal(`[{...}, {...}]`, &items)

Пример вывода:

[& {iPhone 1000} & {A Good Post Lorem ipsum ...}]

...