Unmarshal JSON с произвольными парами ключ / значение для структурирования - PullRequest
2 голосов
/ 08 апреля 2019

Проблема

Найдено много похожих вопросов (название), но ни один из них не решил мою проблему, поэтому вот она.

У меня есть строка JSON, которая содержит некоторые известные поля (должны присутствовать всегда)плюс любое количество неизвестных / произвольных полей.

Пример

{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}

В этом примере known1 и known2 являются известными полями.unknown1 и unknown2 - произвольные / неизвестные поля.

Неизвестные поля могут иметь любое имя (ключ) и любое значение.Тип значения может быть либо string, bool, float64, либо int.

Я хочу найти самый простой и изящный (идиоматический) способ для синтаксического анализа сообщения, подобного этому.

Myрешение

Я использовал следующую структуру:

type Message struct {
    Known1   string `json:"known1"`
    Known2   string `json:"known2"`
    Unknowns []map[string]interface{}
}

Ожидаемый результат

С этой структурой и приведенным выше примером сообщения JSON я хочу получить Messageследующее (вывод из fmt.Printf("%+v", msg)):

{Known1:foo Known2:bar Unknowns:[map[unknown1:car] map[unknown2:1]]}

Попытки

1.Простой немаршал

https://play.golang.org/p/WO6XlpK_vJg

Это не работает, Unknowns не заполнено оставшимися неизвестными парами ключ / значение, как ожидалось.

2.Двойной unmarshal

https://play.golang.org/p/Mw6fOYr-Km8

Это работает, но мне понадобилось два unmarshals, один для заполнения известных полей (используя тип псевдонима, чтобы избежать бесконечного цикла) и второй для получения всех полейкак map[string]interface{} и обработать неизвестных.

3.Немаршальное и типовое преобразование

https://play.golang.org/p/a7itXObavrX

Это работает и кажется лучшим вариантом среди моих решений.

Любой другой вариант?

Вариант 2 и 3работать, но мне любопытно, есть ли у кого-нибудь более простое и элегантное решение.

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

Вероятно, не существует существующего решения только для вашей ситуации. В качестве дополнения к вашим решениям вы можете попробовать использовать необработанные библиотеки синтаксического анализа, такие как:

Последний - мой, и у него есть некоторые незаконченные функции, но сырой анализ сделан.

Вы также можете использовать отражение с библиотеками выше для установки известных полей в структуре.

0 голосов
/ 08 апреля 2019

TMTOWTDI, и я думаю, что вы нашли разумное решение.Другой вариант, который вы могли бы рассмотреть - который, я думаю, похож на ваш вариант 2 - это разархивировать его на map[string]interface{}.

, затем установить диапазон между ключами и значениями и делать с данными все, что вам нужно., запуск утверждений типа на значения по мере необходимости.В зависимости от того, что вам нужно сделать, вы можете полностью пропустить структуру или заполнить ее.

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonMsg := `{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}`
    var msg map[string]interface{}
    fmt.Println(json.Unmarshal([]byte(jsonMsg), &msg))
    fmt.Printf("%+v", msg)
}

печать

<nil>
map[known1:foo known2:bar unknown1:car unknown2:1]

https://play.golang.org/p/Bl99Cq5tFWW

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