MongoDB使用bson.Raw从查询中返回整个JSON

时间:2017-02-22 07:42:28

标签: json mongodb go mgo

我试图搜索此文档:

"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)

更新

关注How to marshal json string to bson document in golang for writing to MongoDB?,我做了:

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

让我:

json: unknown constant "l"

正如您所看到的,我必须从Raw type中提取Data,我不认为这是最好的方法,因为{{1}没有使用的字段。另外,这个' l'是什么?

更新2

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

Kind

它对我有用:)

但是,我仍然忽略了var a bson.M fmt.Println(bson.Unmarshal(dialog.Dialog.Data, &a)) fmt.Println(a) 类型的Kind字段。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:1)

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

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

您可以执行的操作是将interface{}类型的值解组,然后使用json.Marshal()“呈现”JSON表示。

如果您希望这是“自动”,您可以创建一个名为JSONStr的新类型,并且可以通过它实现bson.Setterbson.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{}将“涵盖”所有数据结构。如果您知道它是一个对象,您可以使用地图。如果您知道它是一个数组,您可以使用切片等。您也可以使用任何具体类型。