英文:
Custom marshalling to bson and JSON (Golang & mgo)
问题
我在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(content)
return nil
}
现在我还想能够使用mgo Golang库将其编组和解组到Mongo数据库中。问题是,我已经有存储为base64编码字符串的文档,所以我必须保持这样的格式。我尝试了以下操作:
func (b Base64Data) GetBSON() (interface{}, error) {
return base64.StdEncoding.EncodeToString([]byte(b)), nil
}
func (b *Base64Data) 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,但似乎只有getter正常工作。
从base64编码的字符串进行JSON解组是有效的,同样将其编组到数据库中也是有效的。但是,似乎根本没有调用解组的setter。
有人能否建议我漏掉了什么,以便我能够正确地将解码后的数据保存在内存中,但作为编码字符串类型返回?
英文:
I have the following type in Golang:
type Base64Data []byte
In order to support unmarshalling a base64 encoded string to this type, I did the following:
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
}
Now I also want to be able to marshal and unmarshal it to mongo database, using mgo Golang library.
The problem is that I already have documents there stored as base64 encoded string, so I have to maintain that.
I tried to do the following:
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
}
So that after unmarshaling, the data is already decoded, so I need to encode it back, and return it as a string so it will be written to db as a string (and vice versa)
For that I implemented bson getter and setter, but it seems only the getter is working properly
JSON unmarshaling from base64 encoded string works, as well marshaling it to database. but unmarshling setter seems to not be called at all.
Can anyone suggest what I'm missing, so that I'll be able to properly hold the data decoded in memory, but encoded string type?
This is a test I tried to run:
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))
答案1
得分: 2
你可以使用bson.Marshal()
来序列化map
和结构体值,但不能序列化其他类型的值。
如果你想进行测试,可以将一个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)
}
这将把数据保存为Base64编码的字符串形式。
当然,如果你想将其加载回Base64Data
类型的值,你还需要定义SetBSON(raw Raw) error
方法(bson.Setter
接口)。
英文:
You can't marshal any value with bson.Marshal()
, only maps and struct values.
If you want to test it, pass a map
, e.g. bson.M
to bson.Marshal()
:
var x = Base64Data{0x01, 0x02, 0x03}
dd, err := bson.Marshal(bson.M{"data": x})
fmt.Println(string(dd), err)
Your code works as-is, and as you intend it to. Try to insert a wrapper value to verify it:
c := sess.DB("testdb").C("testcoll")
var x = Base64Data{0x01, 0x02, 0x03}
if err := c.Insert(bson.M{
"data": x,
}); err != nil {
panic(err)
}
This will save the data as a string
, being the Base64 encoded form.
Of course if you want to load it back into a value of type Base64Data
, you will also need to define the SetBSON(raw Raw) error
method too (bson.Setter
interface).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论