json - 编码结构时用嵌入式 json 替换 ObjectId

标签 json mongodb go

我正在使用 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 中(代替原始 ObjectId ), 像这样:

{
    "id": "...",
    "title": "My awesome post",
    "owner": {
        "id": "...",
        "name": "Cody"
    }
}

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

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 背景,在这种情况下,这类功能微不足道。

编辑

为了澄清一些事情,这里有一些不正确的 Go 代码显示了我想做的事情

func getPostJSON() []byte {
    p := LookupPost(...)
    u := LookupUser(p.Owner, ...)

    uj, _ := json.Marshal(u)
    p.Owner = uj // can't do this in Go

    pj, _ := json.Marshal(p)

    return pj
}

最佳答案

我不熟悉 MongoDB 或 bson.ObjectId,但是你能用你自己的类型替换你的 User 字段并让 MongoDB 轻松地为你填写吗?用户的 bson.ObjectId?

如果是这样,您可以将用户对象 ID 包装到他们自己的实现 json.Marshaler 接口(interface)的类型中。例如:

// 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"
  }
}

关于json - 编码结构时用嵌入式 json 替换 ObjectId,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30611086/

相关文章:

c# - 查找所有集合中字段的最大值

mongodb - 在前端使用丑陋的 mongodb _ids

PHP to Go 使用 Unix 域套接字

php - 检查用户名是否存在于Android代码中

json - 如何循环遍历 JSON 对象数组?

java - 从 GridFS 读取时不显示非 ASCII 字符

unit-testing - 在 golang 中模拟外部依赖

arrays - 从重复范围创建函数

javascript - 从文件 express js 提供 json

javascript - PHP json在JavaScript中自动排序