我可以使用 JSON 标签作为 mgo 中的 BSON 标签吗?

huangapple go评论93阅读模式
英文:

Can I use json tags as bson tags in mgo?

问题

在我的项目中,我正在使用thrift,thrift会生成以下代码:

type CvJdRelationInfo struct {
    JdId            string `thrift:"jdId,1" json:"jdId"`
    CvId            string `thrift:"cvId,2" json:"cvId"`
    Status          int16  `thrift:"status,3" json:"status"`
    AcceptTimestamp int64  `thrift:"acceptTimestamp,4" json:"acceptTimestamp"`
}

如你所见,thrift已经生成了json标签(但没有bson标签),当我使用mgo保存记录时,mgo会自动转换:

  • JdId -> jdid
  • CvId -> cvid
  • Status -> status
  • AcceptTimeStamp -> accepttimestamp

我需要的是:

type CvJdRelationInfo struct {
    JdId            string `thrift:"jdId,1" json:"jdId" bson:"jdId"`
    CvId            string `thrift:"cvId,2" json:"cvId" bson:"cvId"`
    Status          int16  `thrift:"status,3" json:"status" bson:"status"`
    AcceptTimestamp int64  `thrift:"acceptTimestamp,4" json:"acceptTimestamp" bson:"acceptTimestamp"`
}

如你所见,bson标签json标签相同。我可以使用json标签作为bson标签吗?

英文:

I am using thrift in my project, thrift will generate code as follow:

type CvJdRelationInfo struct {
	JdId            string `thrift:"jdId,1" json:"jdId"`
	CvId            string `thrift:"cvId,2" json:"cvId"`
	Status          int16  `thrift:"status,3" json:"status"`
	AcceptTimestamp int64  `thrift:"acceptTimestamp,4" json:"acceptTimestamp"`
}

as you see thrift already generate json tags(but no bson tags), when I use mgo save record, mgo will auto convert:

JdId -> jdid
CvId -> cvid
Status -> status
AcceptTimeStamp -> accepttimestamp

what I needed is:

type CvJdRelationInfo struct {
	JdId            string `thrift:"jdId,1" json:"jdId" bson:"jdId"`
	CvId            string `thrift:"cvId,2" json:"cvId" bson:"cvId"`
	Status          int16  `thrift:"status,3" json:"status" bson:"status"`
	AcceptTimestamp int64  `thrift:"acceptTimestamp,4" json:"acceptTimestamp" bson:"acceptTimestamp"`
}

as your can see, bson tags is the same as json tags. Can I use json tags as bson tags?

答案1

得分: 2

MongoDB实际上将数据存储为二进制JSON(bson),这与JSON不同。这可能会有点令人困惑,因为如果你使用mongo shell访问数据库,你会得到原始的JSON,但实际上这是一种转换,而不是存储格式。因此,在将数据存储到数据库时,“mgo”驱动程序将其序列化为bson

这种序列化会忽略json导出键,并通过默认使用结构字段的小写版本来选择适当的名称(参见bson.Marshal go doc)。如果指定了bson导出键,它将忽略结构字段名称,并使用您指定的bson导出键。

例如,

type User struct {
    Name string
    UserAge int `bson:"age"`
    Phone string `json:"phoneNumber"`
}

将在MongoDB中产生以下结构:

{
    "name": "",
    "age": 0,
    "phone": ""
}

所以看起来你的结构字段应该能够处理大部分情况。

唯一可能在你不注意的情况下会出现问题的是,如果你不指定bson导出键,你就无法使用bson:",omitempty"来忽略空字段,或者使用bson:",inline"来序列化嵌入的结构。

例如,这是如何处理嵌入结构的:

type Employee struct {
    User `bson:",inline"`
    JobTitle string
    EmployeeId string
    Salary int
}

这些内容在我提供的链接中有详细说明。希望能对你有所帮助!

英文:

MongoDB actually stores the data as binary JSON (bson), which is distinct from JSON. It's slightly confusing because if you access the database using the mongo shell, you get back raw JSON, but it's actually a conversion, it's not the storage format. So in storing the data to the database, the "mgo" driver serializes as bson.

This serializing ignores the json export keys, and chooses the appropriate name by defaulting to the lowercase version of your struct field. (See the bson.Marshal go doc.) If you specify a bson export key, it will then ignore the struct field name and go with whatever you have specified as the bson export key.

For example,

<!-- language: lang-go -->

type User struct {
    Name string
    UserAge int `bson:&quot;age&quot;`
    Phone string `json:&quot;phoneNumber&quot;`
}

will result in the following structure in MongoDB:

{
    &quot;name&quot;: &quot;&quot;,
    &quot;age&quot;: 0,
    &quot;phone&quot;: &quot;&quot;
}

So it seems like your struct fields should handle most things for you.

The one 'gotcha' that you might not see until it bites you is, if you don't specify the bson export keys, you don't have the ability to do bson:&quot;,omitempty&quot; for leaving out blank fields, or bson:&quot;,inline&quot; for marshaling embedded (or nested) structs.

For instance, this is how you would handle embedded structs:

type Employee struct {
    User `bson:&quot;,inline&quot;`
    JobTitle string
    EmployeeId string
    Salary int
}

These sorts of things are specified in that link I provided on bson.Marshal. Hope that helps!

答案2

得分: 2

你可以通过以下方式更改默认的编码器/解码器:

mongo_addr := "mongodb://localhost:27017/"
structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
rb := bson.NewRegistryBuilder()
// 注册结构体编解码器
rb.RegisterDefaultEncoder(reflect.Struct, structcodec)
rb.RegisterDefaultDecoder(reflect.Struct, structcodec)
clientOptions := options.Client().SetRegistry(rb.Build()).ApplyURI(mongo_addr)

mgclient, err := mongo.Connect(ctx, clientOptions)
if err != nil {
    panic(err)
}

现在在编组/解组期间将使用json标签而不是bson标签。当你使用既属于bson又属于json的标签时,这个技巧特别有用。

顺便说一下,这些clientOptions也可以在集合和数据库级别上设置。

英文:

you can change the default encoder/decoder in the following way:

mongo_addr := &quot;mongodb://localhost:27017/&quot;
structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
rb := bson.NewRegistryBuilder()
// register struct codec
rb.RegisterDefaultEncoder(reflect.Struct, structcodec)
rb.RegisterDefaultDecoder(reflect.Struct, structcodec)
clientOptions := options.Client().SetRegistry(rb.Build()).ApplyURI(mongo_addr)

mgclient, err := mongo.Connect(ctx, clientOptions)
if err != nil {
	panic(err)
}

Now during marshaling/unmarshalling json tag is used instead of bson.
This trick is a particularly useful when you use tags that both bson and json belong to.

By the way, those clientOptions can be set on collection and database levels too

答案3

得分: 0

你可以使用以下内容(来自thrift测试文件git.apache.org/thrift.git/lib/go/test/GoTagTest.thrift):

struct tagged {
    1: string string_thing,
    2: i64 int_thing (go.tag = "json:\"int_thing,string\""),
    3: optional i64 optional_int_thing
}
英文:

You can use the following (From thrift test file git.apache.org/thrift.git/lib/go/test/GoTagTest.thrift)

struct tagged {
    1: string string_thing,
    2: i64 int_thing (go.tag = &quot;json:\&quot;int_thing,string\&quot;&quot;),
    3: optional i64 optional_int_thing
}

huangapple
  • 本文由 发表于 2015年11月11日 10:45:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/33643442.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定