2017-02-03 14 views
1

У меня есть следующий тип в Golang:Пользовательские сортировочная для BSON и JSON (Golang и Ий)

type Base64Data []byte

В целях поддержки демаршаллизации кодировки Base64 к этому типу, я сделал следующее:

func (b *Base64Data) UnmarshalJSON(data []byte) error { 
    if len(data) == 0 { 
     return nil 
    } 

    content, err := base64.StdEncoding.DecodeString(string(data[1 : len(data)-1])) 
    if err != nil { 
     return err 
    } 

    *b = []byte(xml) 
    return nil 
} 

Теперь я также хочу, чтобы иметь возможность маршалировать и развязывать его в базу данных монго, используя библиотеку mgo Golang. Проблема в том, что у меня уже есть документы, хранящиеся в кодировке base64, поэтому я должен это поддерживать. я попытался сделать следующее:

func (b Base64Data) GetBSON() (interface{}, error) { 
    return base64.StdEncoding.EncodeToString([]byte(b)), nil 
} 

func (b *Base64DecodedXml) SetBSON(raw bson.Raw) error { 
    var s string 
    var err error 
    if err = raw.Unmarshal(&s); err != nil { 
     return err 
    } 
    *b, err = base64.StdEncoding.DecodeString(s) 
    return err 
} 

Так что после демаршалинга, данные уже декодируется, так что мне нужно кодировать его обратно и вернуть его в виде строки, так что это будет записано в БД в виде строки (и наоборот) Для этого я внедрил bson getter и setter, но кажется, что только геттер работает правильно

JSON unmarshaling из кодированной строки base64 работает, а также маршалинг его в базу данных. но неподготовленный сеттер, похоже, вообще не называется.

Может кто-нибудь предположить, что мне не хватает, чтобы я мог правильно хранить данные, декодированные в памяти, но закодированные строки типа?

Это тест, который я попытался запустить:

b := struct { 
    Value shared.Base64Data `json:"value" bson:"value"` 
}{} 
s := `{"value": "PHJvb3Q+aGVsbG88L3Jvb3Q+"}` 
require.NoError(t, json.Unmarshal([]byte(s), &b)) 
t.Logf("%v", string(b.Value)) 
b4, err := bson.Marshal(b) 
require.NoError(t, err) 
t.Logf("%v", string(b4)) 
require.NoError(t, bson.Unmarshal(b4, &b)) 
t.Logf("%v", string(b.Value)) 
+0

Ваш код работает. Пожалуйста, покажите нам, как вы его используете. – icza

+0

@icza Добавлен пример – buddy123

+0

А что такое 'b3' в вашем коде? – icza

ответ

1

Вы не можете маршал любого значения с bson.Marshal(), только картами и значением структуры.

Если вы хотите его протестировать, отправьте map, например. bson.M к bson.Marshal():

var x = Base64Data{0x01, 0x02, 0x03} 

dd, err := bson.Marshal(bson.M{"data": x}) 
fmt.Println(string(dd), err) 

Ваш код работает как есть, и как вы намерены его. Попробуйте вставить значение обертку, чтобы проверить его:

c := sess.DB("testdb").C("testcoll") 

var x = Base64Data{0x01, 0x02, 0x03} 
if err := c.Insert(bson.M{ 
    "data": x, 
}); err != nil { 
    panic(err) 
} 

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

Конечно, если вы хотите загрузить его обратно в значение типа Base64Data, вам также необходимо определить метод SetBSON(raw Raw) error (bson.Setter).

+0

спасибо. Я тестировал это неправильно. Действительно, марсилинг для бсон работает хорошо. Поэтому мне действительно нужно завершить свою реализацию, написав сеттер. но это, кажется, не называется вообще. Я отредактировал свой вопрос, не могли бы вы предложить, что я делаю неправильно с установщиком? – buddy123

+0

@ buddy123 Вы сохраняете его как значение типа 'string', поэтому вы должны отменить необработанное значение в значение типа' string', а не '[] byte'. – icza

+0

это меня смутило. Вы правы, но он все равно не работает, когда я отключаю строку. Я отредактировал мой сеттер – buddy123