2015-06-01 6 views
4

Я использую хранилище значений ключей в качестве бэкэнд для моего приложения 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` 
} 

Две части Вопрос:

  1. Есть ли способ, чтобы избежать повторных демаршализует (или что-то я не должен даже заботиться о)
  2. как я могу понять, какой структура для распаковать json.RawMessage в (который также позволяет для вложенных данных JSON)

Update: первоначальный ответ предоставляется @chendesheng позволяет мне т o узнайте тип, но не отключайте его снова в структуру после того, как этот тип был определен (что мне нужно сделать), поэтому, основываясь на разговоре в комментариях к его/ее ответу, меня интересовала бы любая из этих возможностей

a) Сделайте копию json.RawMessage, немаршали в интерфейс, как вы показали (по дате chendesheng), а затем отмените копирование itno структуры, как только вы знаете тип (из-за того, что он не подключен к интерфейсу)?

б) использовать регулярные выражения для определения типа, а затем распаковать в структуры такого типа, как только это известный

+0

Не обижайтесь, но я думаю, вы должны пересмотреть свой дизайн, потому что вы должны быть в состоянии избежать такого решения во время выполнения или, по крайней мере, использовать флаг типа какого-либо рода, чтобы избежать этого более свободного интроспективного средства решения о десериализации , Вы обрабатываете данные из ВАШЕ ДБ, как если бы это было от какой-то неконтролируемой и непредсказуемой третьей стороны, я рекомендую против этого. – evanmcdonnal

+0

@evanmcdonnal спасибо за ввод. Я буду принимать это во внимание, и если я найду лучший способ сделать это, я, однако, не верю, что отношусь к тому, как будто это от непредсказуемой третьей стороны.Дело в том, что структура json-документов не одинакова и поэтому должна быть развязана в разные структуры, и поэтому мне нужно выяснить, что представляет собой json, прежде чем я выберу, какая структура будет отменена в – BrainLikeADullPencil

+0

Да, json представляет разные типы. Вы также можете сохранить информацию о типе в своей базе данных и использовать ее для принятия 100% -ного окончательного решения о том, какой тип он находится перед вызывающим Unmarshal, вы используете unmarshal, как будто это try/catch, а не использовать информацию типа info + select to unmarshal в правильный тип без неопределенного поведения во время выполнения. – evanmcdonnal

ответ

4

Tow способы проверки типа структуры:

  1. json.RawMessage к распаковать карту [строка] интерфейс {}
  2. Используйте регулярное выражение для извлечения строкового типа

http://play.golang.org/p/gfP6P4SmaC

+0

Меня интересует этот ответ, но я думаю, вы неправильно поняли структуру моих данных. В каждом из моих документов есть поле «foo» (это пространство имен верхнего уровня для каждого json-документа). То, что мне нужно определить, - это значение поля типа, когда я снова отключу его. Можете ли вы повторить свой play.golang.org, чтобы показать мне это? – BrainLikeADullPencil

+1

Вы можете сделать то же самое с объектом foo. http://play.golang.org/p/MDfoE8jhKV – chendesheng

+0

, но после того, как я отформатирую его в интерфейсе (и выясню, что такое значение поля типа), я не могу его снова отмонтировать в структуру Bar (теперь что я знаю, что структура Bar будет подходящей структурой), не так ли? Мне нужно иметь возможность получить документ в соответствующую структуру. – BrainLikeADullPencil

Смежные вопросы