2017-02-22 26 views
1

Я пытаюсь найти этот документ:MongoDB Возврат весь JSON из запроса с использованием bson.Raw

"meta": { 
    "pageId": "...", 
    "userId": "...", 
    "ver": "0", 
}, 
"dialog": { 
... 

} 

и получить весь "dialog" как JSON, поэтому я создал эту структуру:

type Dialog struct { 
    Dialog bson.Raw `json:"dialog" bson:"dialog"` 
} 

Так я запросить этот документ так:

dialog := Dialog{} 
query := c.Find(locate).One(&dialog) 

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

Вопрос в том, как размонтировать его в объект JSON?

Единственное, что я нашел об этом являются Marshal into a bson.Raw (который не объясняет, как распаковать в JSON)

Update

После How to marshal json string to bson document in golang for writing to MongoDB?, я сделал:

fmt.Println(bson.UnmarshalJSON(dialog.Dialog.Data, &a)) 

, который получает меня:

json: unknown constant "l" 

Как вы можете видеть, мне нужно было извлечь Data из Raw type, я не думаю, что это лучший способ сделать это, так как есть поле Kind, которое не используется. Кроме того, что это 'l'?

Update 2

Я думал, что я должен был распаковать в тип JSON для того, чтобы работать с ним, но я обнаружил, что лучше распаковать на карту непосредственно, так вот она:

var a bson.M 
fmt.Println(bson.Unmarshal(dialog.Dialog.Data, &a)) 
fmt.Println(a) 

Он работал для меня :)

Однако, я все еще не обращая внимания на Kind поле Raw типа. Есть ли лучший способ сделать это?

ответ

1

JSON не является типом, поэтому вы не можете развязать значение типа JSON. JSON - текстовое представление некоторых структурированных данных.

bson.Raw также не соответствует представлению JSON, поэтому неизбежно произойдет какое-то преобразование.

Что вы можете сделать, это немаршалить значение типа interface{}, а затем использовать json.Marshal() для «визуализации» представления JSON.

Если вы хотите, чтобы это было «автоматическим», вы можете создать новый тип, называемый JSONStr, и вы можете реализовать его интерфейсыи bson.Getter.

Вот как это может выглядеть следующим образом:

type JSONStr string 

func (j *JSONStr) SetBSON(raw bson.Raw) (err error) { 
    var i interface{} 
    if err = raw.Unmarshal(&i); err != nil { 
     return 
    } 
    data, err := json.Marshal(i) 
    if err != nil { 
     return 
    } 
    *j = JSONStr(data) 
    return 
} 

func (j *JSONStr) GetBSON() (interface{}, error) { 
    var i interface{} 
    if err := json.Unmarshal([]byte(*j), &i); err != nil { 
     return nil, err 
    } 
    return i, nil 
} 

И с помощью этого JSONStr Тип:

type Dialog struct { 
    Dialog JSONStr `bson:"dialog"` 
} 

Update:

Если вы действительно не хотите, текст JSON представительство, просто используйте тип interface{}:

type Dialog struct { 
    Dialog interface{} `bson:"dialog"` 
} 

И получить текст JSON как это:

var dialog Dialog 
// load a dialog 
data, err := json.Marshal(dialog.Dialog) 
if err != nil { 
    // handle error 
} 
fmt.Println(string(data)) 

(В основном это то, что метод JSONStr.SetBSON() сделал точно.)

Обратите внимание, что interface{} будет "покрывать" все структуры данных. Если вы знаете, что это объект, вы можете использовать карту. Если вы знаете, что это массив, вы можете использовать срез и т. Д. Вы также можете использовать любой конкретный тип.

+0

Я действительно понял, что я не хочу иметь json, я просто хотел иметь дело с данными в некотором роде. Теперь я нашел функцию Unmarshal и развязал ее в карту. Однако, делая это, я игнорирую поле Raw.kind, я напрямую извлекаю Raw.Data. Не могли бы вы посмотреть мое обновление2? Это лучший способ справиться с генерическими данными, возвращаемыми из запроса MongoDB? –

+0

@GuerlandoOCs Нет, это не так. Поле «Тип» должно указывать, как интерпретировать поле «Данные». Игнорирование это вызовет проблемы. Кроме того, пусть пакет 'mgo' обрабатывает это для вас. Кроме того, разметка на карте также даст вам ошибки, если это значение является массивом. Чтобы охватить все случаи, отключите значение типа 'interface {}', как это было в моем ответе. – icza

+0

Вы правы, я сделал это, и все получилось. Однако, чтобы получить доступ к своим членам, я должен признать, что это карта и на нее наложено. Неужели так плохо? Потому что, как я узнал, что он будет развязан на карте? –