编组结构时用嵌入的 json 替换 ObjectId

我正在使用 Go 和 MongoDB 构建一个 RESTful API,并且在将一个文档的 JSON 嵌入另一个文档的 JSON 中遇到了一些困难。这是我正在尝试完成的一个玩具示例。我有以下模式:


type Post struct {

    ID    bson.ObjectId `json:"id,omitempty"`

    Title string        `json:"title,omitempty"`

    Owner bson.ObjectId `json:"owner,omitempty"` // references a User

}


type User struct {

    ID   bson.ObjectId `json:"id,omitempty"`

    Name string        `json:"name,omitempty"`

}

在为帖子创建 JSON 时,我想首先在 MongoDB 中查找帖子的所有者,并将生成的用户嵌入到所述帖子的 JSON(代替原始 JSON ObjectId)中,如下所示:


{

    "id": "...",

    "title": "My awesome post",

    "owner": {

        "id": "...",

        "name": "Cody"

    }

}

除了使用 手动构建 JSON 之外,我不太确定如何完成此操作map[string]interface{},如下所示:


post := LookupPost(...)

user := LookupUser(post.Owner)


m := map[string]interface{}{

    "id": post.ID,

    "title": post.Title,

    "owner": map[string]interface{}{

        "id": user.ID,

        "name": user.Name,

    },

}


b, _ := json.Marshal(m)

理想情况下,我能够利用json每个结构定义中的标签并自动插入字段。

我是否遗漏了什么,或者我试图做的事情是不可能的?或者我只是没有正确地在 Go 中接近 MongoDB/JSON?从正确的角度来看,我来自 Node.js 背景,在那里这种功能是微不足道的。


回首忆惘然
浏览 188回答 2
2回答

Helenr

我不熟悉 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) {&nbsp; &nbsp; user, err := LookupUser(oid.ObjectId)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return nil, err&nbsp; &nbsp; }&nbsp; &nbsp; return json.Marshal(user)}type Post struct {&nbsp; &nbsp; ID&nbsp; &nbsp; bson.ObjectId `json:"id,omitempty"`&nbsp; &nbsp; Title string&nbsp; &nbsp; &nbsp; &nbsp; `json:"title,omitempty"`&nbsp; &nbsp; Owner ownerObjID&nbsp; &nbsp; `json:"owner,omitempty"` // <-- is this type wrapping doable/easy with MongoDB?}type User struct {&nbsp; &nbsp; ID&nbsp; &nbsp;bson.ObjectId `json:"id,omitempty"`&nbsp; &nbsp; Name string&nbsp; &nbsp; &nbsp; &nbsp; `json:"name,omitempty"`}func main() {&nbsp; &nbsp; post := LookupPost()&nbsp; &nbsp; b, err := json.MarshalIndent(post, "", "&nbsp; ")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("JSON:\n%s\n", b)}// Some stubs for demo:func LookupPost() Post {&nbsp; &nbsp; return Post{&nbsp; &nbsp; &nbsp; &nbsp; ID:&nbsp; &nbsp; "postID001",&nbsp; &nbsp; &nbsp; &nbsp; Title: "Ima Test",&nbsp; &nbsp; &nbsp; &nbsp; Owner: ownerObjID{"ownerID002"},&nbsp; &nbsp; }}func LookupUser(id bson.ObjectId) (User, error) {&nbsp; &nbsp; return User{&nbsp; &nbsp; &nbsp; &nbsp; ID:&nbsp; &nbsp;id,&nbsp; &nbsp; &nbsp; &nbsp; Name: "name for " + string(id),&nbsp; &nbsp; }, nil}Playground给我:JSON:{&nbsp; "id": "postID001",&nbsp; "title": "Ima Test",&nbsp; "owner": {&nbsp; &nbsp; "id": "ownerID002",&nbsp; &nbsp; "name": "name for ownerID002"&nbsp; }}

慕少森

所以我实际上发现了一个更清晰的解决这个问题的方法:type Post struct {&nbsp; &nbsp; ID bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`&nbsp; &nbsp; Title string `bson:"title,omitempty" json:"title,omitempty"`&nbsp; &nbsp; Owner UserRef `bson:"owner,omitempty" json:"owner,omitempty"`}type User struct {&nbsp; &nbsp; ID&nbsp; &nbsp;bson.ObjectId `json:"id,omitempty"`&nbsp; &nbsp; Name string&nbsp; &nbsp; &nbsp; &nbsp; `json:"name,omitempty"`}type UserRef bson.ObjectIdfunc (ref UserRef) GetBSON() (interface{}, error) {&nbsp; &nbsp; return bson.ObjectId(ref), nil}func (ref UserRef) MarshalJSON() ([]byte, error) {&nbsp; &nbsp; u := LookupUserInMongoDB(ref)&nbsp; &nbsp; return json.Marshal(u)}这是它的工作原理——在将 Post 转换为 bson 时,mgo 无法将 UserRef 存储为 ObjectId,因此我们可以实现GetBSONUserRef的方法以返回底层 ObjectId。这允许我们将 Owner 作为 ObjectId 存储在数据库中。而且,就像在@DaveC 的回答中一样,我们实现了MarshalJSONUserRef的方法,以便在将 Post 转换为 json 时,我们可以用实际嵌入的用户替换 ObjectId。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go