2 回答
TA贡献1780条经验 获得超4个赞
我不熟悉 MongoDB 或bson.ObjectId,但是您能否将您自己的类型替换为您的User字段,并让 MongoDB 轻松地从用户的bson.ObjectId.
如果是这样,您可以将用户对象 id 包装到他们自己的实现json.Marshaler接口的类型中。例如:
// Embedded (instead of `type x bson.ObjectId`) so that we
// get all the methods and satisfy all the interfaces that
// bson.ObjectId does. Hopefully that's engough to allow MongoDB
// to fill in fields of this type from a database??
type ownerObjID struct{ bson.ObjectId }
// Here we marshal the results of looking up the user from the id
// rather than just the ID itself.
func (oid ownerObjID) MarshalJSON() ([]byte, error) {
user, err := LookupUser(oid.ObjectId)
if err != nil {
return nil, err
}
return json.Marshal(user)
}
type Post struct {
ID bson.ObjectId `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Owner ownerObjID `json:"owner,omitempty"` // <-- is this type wrapping doable/easy with MongoDB?
}
type User struct {
ID bson.ObjectId `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
func main() {
post := LookupPost()
b, err := json.MarshalIndent(post, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Printf("JSON:\n%s\n", b)
}
// Some stubs for demo:
func LookupPost() Post {
return Post{
ID: "postID001",
Title: "Ima Test",
Owner: ownerObjID{"ownerID002"},
}
}
func LookupUser(id bson.ObjectId) (User, error) {
return User{
ID: id,
Name: "name for " + string(id),
}, nil
}
Playground
给我:
JSON:
{
"id": "postID001",
"title": "Ima Test",
"owner": {
"id": "ownerID002",
"name": "name for ownerID002"
}
}
TA贡献2019条经验 获得超9个赞
所以我实际上发现了一个更清晰的解决这个问题的方法:
type Post struct {
ID bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`
Title string `bson:"title,omitempty" json:"title,omitempty"`
Owner UserRef `bson:"owner,omitempty" json:"owner,omitempty"`
}
type User struct {
ID bson.ObjectId `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
type UserRef bson.ObjectId
func (ref UserRef) GetBSON() (interface{}, error) {
return bson.ObjectId(ref), nil
}
func (ref UserRef) MarshalJSON() ([]byte, error) {
u := LookupUserInMongoDB(ref)
return json.Marshal(u)
}
这是它的工作原理——在将 Post 转换为 bson 时,mgo 无法将 UserRef 存储为 ObjectId,因此我们可以实现GetBSONUserRef的方法以返回底层 ObjectId。这允许我们将 Owner 作为 ObjectId 存储在数据库中。而且,就像在@DaveC 的回答中一样,我们实现了MarshalJSONUserRef的方法,以便在将 Post 转换为 json 时,我们可以用实际嵌入的用户替换 ObjectId。
- 2 回答
- 0 关注
- 185 浏览
添加回答
举报