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" 所有数据结构。如果您知道它是一个对象,则可以使用地图。如果你知道它是一个数组,你可以使用切片等。你也可以使用任何具体类型。
我正在尝试搜索此文档:
"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" 所有数据结构。如果您知道它是一个对象,则可以使用地图。如果你知道它是一个数组,你可以使用切片等。你也可以使用任何具体类型。