Я использую хранилище значений ключей в качестве бэкэнд для моего приложения golang, с датой, служащей ключом (чтобы сортировать записи) и json-документами в качестве значений. Пространство имен верхнего уровня json (foo
) и type
и date
присутствуют в каждом json-документе, который я храню, но в остальном есть некоторые отличия (особенно в отношении некоторых вложенных json-данных), поэтому, когда keyI'm вытягивает из база данных, я действительно не знаю, что я вытаскиваю в любое время, когда я зацикливаюсь. Вот пример данных JSonunmarshal вложенный json без знания структуры
{ "foo": { "id":"124", "type":"baz", "rawdata":[123, 345,345],"epoch": "1433120656704"}}
{ "foo" : { "id":"234", "type":"bar", "rawdata":[{"key":"dog", "values":[123,234]}, {"key":"cat", "values":[23, 45]}], "epoch":"1433120656705"}}
, когда я тяну из базы данных, то первое, что я делаю, это распаковать каждую запись в map[string]*json.RawMessage
иметь дело с foo
именами
//as I'm looping through the entries in the database
var objmap map[string]*json.RawMessage
if err := json.Unmarshal(dbvalue, &objmap); err !=nil{
return err
}
который Я делаю это благодаря этому SO answer
Однако, в отличие от этого ответа SO, когда мне нужно снова отменить все то, что содержится в пространстве имен foo
, я не знаю, какую структуру следует развязать в
if err :=json.Unmarshal(*objmap["foo"], &bazorbar; err != nil{
return err
}
type Baz struct{
Id string `json:"id"`
Type string `json:"type"`
RawData []int `json:"rawdata"`
Epoch string `json:"epoch"`
}
type Bar struct{
Id string `json:"id"`
Type string `json:"type"`
RawData []*Qux `json:"rawdata"`
Epoch string `json:"epoch"`
}
//nested inside Bar
type Qux struct{
Key string `json:"key"`
Values []int `json:"values`
}
Две части Вопрос:
- Есть ли способ, чтобы избежать повторных демаршализует (или что-то я не должен даже заботиться о)
- как я могу понять, какой структура для распаковать json.RawMessage в (который также позволяет для вложенных данных JSON)
Update: первоначальный ответ предоставляется @chendesheng позволяет мне т o узнайте тип, но не отключайте его снова в структуру после того, как этот тип был определен (что мне нужно сделать), поэтому, основываясь на разговоре в комментариях к его/ее ответу, меня интересовала бы любая из этих возможностей
a) Сделайте копию json.RawMessage, немаршали в интерфейс, как вы показали (по дате chendesheng), а затем отмените копирование itno структуры, как только вы знаете тип (из-за того, что он не подключен к интерфейсу)?
б) использовать регулярные выражения для определения типа, а затем распаковать в структуры такого типа, как только это известный
Не обижайтесь, но я думаю, вы должны пересмотреть свой дизайн, потому что вы должны быть в состоянии избежать такого решения во время выполнения или, по крайней мере, использовать флаг типа какого-либо рода, чтобы избежать этого более свободного интроспективного средства решения о десериализации , Вы обрабатываете данные из ВАШЕ ДБ, как если бы это было от какой-то неконтролируемой и непредсказуемой третьей стороны, я рекомендую против этого. – evanmcdonnal
@evanmcdonnal спасибо за ввод. Я буду принимать это во внимание, и если я найду лучший способ сделать это, я, однако, не верю, что отношусь к тому, как будто это от непредсказуемой третьей стороны.Дело в том, что структура json-документов не одинакова и поэтому должна быть развязана в разные структуры, и поэтому мне нужно выяснить, что представляет собой json, прежде чем я выберу, какая структура будет отменена в – BrainLikeADullPencil
Да, json представляет разные типы. Вы также можете сохранить информацию о типе в своей базе данных и использовать ее для принятия 100% -ного окончательного решения о том, какой тип он находится перед вызывающим Unmarshal, вы используете unmarshal, как будто это try/catch, а не использовать информацию типа info + select to unmarshal в правильный тип без неопределенного поведения во время выполнения. – evanmcdonnal