自定义编组到 bson 和 JSON (Golang & mgo)
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(xml)
return nil
}
现在我还希望能够使用 mgo Golang 库将其编组和解组到 mongo 数据库。
问题是我已经将文档存储为 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
}
所以在解组之后,数据已经被解码,所以我需要将它编码回来,return它作为一个字符串,所以它会作为一个字符串写入数据库(反之亦然)
为此,我实现了 bson getter 和 setter,但似乎只有 getter 工作正常
JSON 从 base64 编码的字符串中解组,以及将其编组到数据库。但是解组 setter 似乎根本没有被调用。
任何人都可以建议我缺少什么,以便我能够正确保存在内存中解码的数据,但编码字符串类型?
这是我试过的测试运行:
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))
您不能使用 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)
您的代码可以正常工作 as-is,并且如您所愿。尝试插入一个包装值来验证它:
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
接口)。
我在 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 库将其编组和解组到 mongo 数据库。 问题是我已经将文档存储为 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
}
所以在解组之后,数据已经被解码,所以我需要将它编码回来,return它作为一个字符串,所以它会作为一个字符串写入数据库(反之亦然) 为此,我实现了 bson getter 和 setter,但似乎只有 getter 工作正常
JSON 从 base64 编码的字符串中解组,以及将其编组到数据库。但是解组 setter 似乎根本没有被调用。
任何人都可以建议我缺少什么,以便我能够正确保存在内存中解码的数据,但编码字符串类型?
这是我试过的测试运行:
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))
您不能使用 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)
您的代码可以正常工作 as-is,并且如您所愿。尝试插入一个包装值来验证它:
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
接口)。