英文:
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:"age"`
Phone string `json:"phoneNumber"`
}
will result in the following structure in MongoDB:
{
"name": "",
"age": 0,
"phone": ""
}
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:",omitempty"
for leaving out blank fields, or bson:",inline"
for marshaling embedded (or nested) structs.
For instance, this is how you would handle embedded structs:
type Employee struct {
User `bson:",inline"`
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 := "mongodb://localhost:27017/"
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 = "json:\"int_thing,string\""),
3: optional i64 optional_int_thing
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论