MongoDB Return 整个 JSON 来自使用 bson.Raw 的查询

MongoDB Return entire JSON from query using bson.Raw

我正在尝试搜索此文档:

"meta": {
    "pageId": "...",
    "userId": "...",
    "ver": "0",
},
"dialog": {
 ...

 }

并将整个 "dialog" 作为 JSON,所以我创建了这个结构:

type Dialog struct {
    Dialog bson.Raw `json:"dialog" bson:"dialog"`
}

所以我这样查询文档:

dialog := Dialog{}
query := c.Find(locate).One(&dialog)

并且当我打印 dialog 时,我得到了一堆数字,我认为它们是来自查询的原始字节。

问题是:如何将其解组为 JSON 对象?

我唯一发现的是 Marshal into a bson.Raw(它没有解释如何解组为 json)

更新

之后,我做了:

fmt.Println(bson.UnmarshalJSON(dialog.Dialog.Data, &a))

这让我:

json: unknown constant "l"

如您所见,我必须从 Raw type 中提取 Data,我认为这不是最好的方法,因为有 Kind 字段没有被使用。另外,这是什么 'l'?

更新 2

我认为我必须将其解组为 JSON 类型才能使用它,但我发现直接将其解组为地图更好,所以这里是:

var a bson.M
fmt.Println(bson.Unmarshal(dialog.Dialog.Data, &a))
fmt.Println(a)

它对我有用:)

但是,我仍然忽略 Raw 类型的 Kind 字段。有更好的方法吗?

JSON 不是类型,因此您无法解组为 JSON 类型的值。 JSON 是一些结构化数据的文本表示。

bson.Raw也不等于JSON表示,所以某种转换是不可避免的。

您可以将 interface{} 类型的值解组,然后使用 json.Marshal() 到 "render" JSON 表示。

如果您希望它成为 "automatic",您可以创建一个名为 JSONStr 的新类型,并且您可以通过它实现 bson.Setter and bson.Getter 接口。

它可能是这样的:

type JSONStr string

func (j *JSONStr) SetBSON(raw bson.Raw) (err error) {
    var i interface{}
    if err = raw.Unmarshal(&i); err != nil {
        return
    }
    data, err := json.Marshal(i)
    if err != nil {
        return
    }
    *j = JSONStr(data)
    return
}

func (j *JSONStr) GetBSON() (interface{}, error) {
    var i interface{}
    if err := json.Unmarshal([]byte(*j), &i); err != nil {
        return nil, err
    }
    return i, nil
}

并使用此 JSONStr 类型:

type Dialog struct {
    Dialog JSONStr `bson:"dialog"`
}

更新:

如果您真的不需要 JSON 文本表示,只需使用类型 interface{}:

type Dialog struct {
    Dialog interface{} `bson:"dialog"`
}

并像这样获取 JSON 文本:

var dialog Dialog
// load a dialog
data, err := json.Marshal(dialog.Dialog)
if err != nil {
    // handle error
}
fmt.Println(string(data))

(基本上这就是 JSONStr.SetBSON() 方法所做的。)

注意 interface{} 将 "cover" 所有数据结构。如果您知道它是一个对象,则可以使用地图。如果你知道它是一个数组,你可以使用切片等。你也可以使用任何具体类型。