Маршал в bson.Raw

Используя gopkg.in/mgo.v2/bson, мне интересно, как преобразовать значение интерфейса{} в значение введите bson.Raw.

В документации для bson.Raw указано:

Используя этот тип, можно неупорядочивать или частично упорядочивать значения.

Но я не могу найти функцию маршала, которая бы возвращала bson.Raw.

Что мне не хватает?

Пример того, что я пытаюсь сделать:

package main

import (
    "fmt"

    "gopkg.in/mgo.v2/bson"
)

func main() {
    // How to avoid a MarshalRaw help function?
    raw, err := MarshalRaw("Hello world")
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", raw)
}

func MarshalRaw(v interface{}) (*bson.Raw, error) {
    bin, err := bson.Marshal(struct{ Raw interface{} }{v})
    if err != nil {
        return nil, err
    }

    var raw struct{ Raw bson.Raw }
    err = bson.Unmarshal(bin, &raw)
    if err != nil {
        return nil, err
    }

    return &raw.Raw, nil
}

Вывод:

&{Вид:2 Данные:[12 0 0 0 72 101 108 108 111 32 119 111 114 108 100 0]}


person ANisus    schedule 13.08.2014    source источник


Ответы (2)


bson.Raw используется как значение как при маршалинге, так и при демаршалинге.

Чтобы преобразовать interface{} в bson.Raw, первое, что нужно сделать, это маршалировать его так, чтобы вы получали простые данные документа, представляющие все, что маршалируется:

    var value interface{} = bson.M{"some": "value"}
    data, err := bson.Marshal(value)
    if err != nil {
            log.Fatal(err)
    }

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

    var doc struct{ Some bson.Raw }
    err = bson.Unmarshal(data, &doc)
    if err != nil {
            log.Fatal(err)
    }

или даже весь документ:

    var doc bson.Raw
    err = bson.Unmarshal(data, &doc)
    if err != nil {
            log.Fatal(err)
    }

Если вам нужен весь документ, а не только поле, вы также можете использовать этот ярлык:

    doc := bson.Raw{3, data}

Константа 3 представляет документ в спецификации bson и, конечно, должен соответствовать предоставленным данным. Поскольку BSON поддерживает документы только верхнего уровня, мы знаем, что это должно быть правильно.

person Gustavo Niemeyer    schedule 13.08.2014

Я считаю, что bson.Raw предназначен для использования в качестве типа переменной.

например: (в воспроизведении)

type Bar struct {
   AnInt int
   AString bson.Raw
}

Поле «AString» будет сохранено в соответствии со структурой bson.Raw, указанной в вашей ссылке.

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

Обратите внимание, что приведенное выше не проверено, не перед машиной, на которой я действительно могу работать в данный момент. Это основано на предположении, что он работает как стандартный пакет encoding/json.

person David Budworth    schedule 13.08.2014
comment
Да, это тоже мое намерение, и оно охватывает частичную декомпозицию структуры. Но когда вы хотите вставить значение Bar в базу данных, вы хотите установить значение AString. Как создать это значение bson.Raw из обычной строки (или любого другого типа)? В конце концов, в документации частично упоминаются значения маршалинга, а решение Playground с использованием отдельной структуры Foo для маршалинга не является частичным. - person ANisus; 13.08.2014
comment
Я добавил пример обходного пути. Хотя это некрасиво. - person ANisus; 13.08.2014