使用Gobson/Mgo解组BSON数据

huangapple go评论96阅读模式
英文:

Unmarshalling BSON data using Gobson/Mgo

问题

我正在接收不同的BSON文档,下面是一个示例:

{ "group" : { "id": ObjectId("11a123456bc345d452d32c0b5"), "name": "SomeName" }, "count1": 6, "count2": 33, "totalCount": 39 }

我尝试使用mgo/gobson将这些数据解组为map[string]interface{},但一直出现错误。解组的代码如下:

var record map[string]interface{}

err := bson.Unmarshal(data, &record)

这导致一个错误,说文档已损坏。查看代码后,我发现它期望字节数组的长度是前几个字节,所以我添加了类似于测试中的代码。

rec := make([]byte, len(data)+6)
binary.LittleEndian.PutUint32(rec, uint32(len(rec)))
copy(rec[4:], data)

这样我就解决了文档损坏的错误,但现在我得到了

Unknown element kind (0x7B)

我在解组上述BSON文档为map时做错了什么?BSON文档本身有问题吗?我不是BSON文档的创建者,但如果需要的话,我可以向他们提供反馈。

英文:

I am receiving different BSON documents, an example seen here:

{ "group" : { "id": ObjectId("11a123456bc345d452d32c0b5"), "name": "SomeName" }, "count1": 6, "count2": 33, "totalCount": 39 }

I am trying to use mgo/gobson to unmarshal this data into a map[string]interface{}, but keep getting an error. The unmarshalling code is

var record map[string]interface{}

err := bson.Unmarshal(data, &record)

This resulted in a error saying the document was corrupted. Looking into the code I saw that it expected the length of the byte array to be the first few bytes so I added code similar to what is found in the tests.

rec := make([]byte, len(data)+6)
binary.LittleEndian.PutUint32(rec, uint32(len(rec)))
copy(rec[4:], data)

This got me past the corrupt document error, but now I am getting

Unknown element kind (0x7B)

What am I doing wrong that I can't easily unmarshal the above BSON document into a map? Is there a problem with the BSON document itself? I am not the creator of the BSON document, but am able to provide feedback to them if necessary.

答案1

得分: 2

我试过了你上面的代码,并且成功让它“工作”起来了。你之所以会得到"Unknown element kind (0x7B)"的错误是因为在BSON规范中没有定义0x7B这种类型的元素。你在文档中的第一个大括号({)的字节值正好是这个未知类型的元素。

经过一些代码调整后,我成功地让它工作,不再出现"unknown kind"的错误。

package main

import (
	"encoding/binary"
	"fmt"

	"gopkg.in/mgo.v2/bson"
)

func main() {
	bsonData := `{ "group" : { "id": ObjectId("11a123456bc345d452d32c0b5"), "name": "SomeName" }, "count1": 6, "count2": 33, "totalCount": 39 }`

	var record map[string]interface{}

	rec := make([]byte, len(bsonData)+6)
	binary.LittleEndian.PutUint32(rec, uint32(len(rec)))
	copy(rec[4:], bsonData)
	// 在 rec 字节变量的开头添加一个换行符似乎可以解决问题
	r := []byte("\n")
	rec[4] = r[0]
	err := bson.Unmarshal(rec, &record)
	if err != nil {
		panic(err)
	}
	fmt.Println(record)
}

我还发现这个答案非常有用:https://stackoverflow.com/a/33129119/2627768

英文:

I tried out your code above and I managed to get it to "work". The reason you are getting

Unknown element kind (0x7B)

is because there is no element of kind 0x7B in the BSON specification. See here http://bsonspec.org/spec.html. The particular unknow element I was getting was the byte value for the first curly bracket({) in your document

{ "group" : { "id": ObjectId("11a123456bc345d452d32c0b5"), "name": "SomeName" }, "count1": 6, "count2": 33, "totalCount": 39 }

after tweaking the code a bit I was able to get it working with out the unknown kind error.

package main

import (
	"encoding/binary"
	"fmt"

	"gopkg.in/mgo.v2/bson"
)

func main() {
	bsonData := `{ "group" : { "id": ObjectId("11a123456bc345d452d32c0b5"), "name": "SomeName" }, "count1": 6, "count2": 33, "totalCount": 39 }`

	var record map[string]interface{}

	rec := make([]byte, len(bsonData)+6)
	binary.LittleEndian.PutUint32(rec, uint32(len(rec)))
	copy(rec[4:], bsonData)
    //Adding a new line to the front of the rec byte variable seems to do the trick
	r := []byte("\n")
	rec[4] = r[0]
	err := bson.Unmarshal(rec, &record)
	if err != nil {
		panic(err)
	}
	fmt.Println(record)
}

I also found this answer to be of great use https://stackoverflow.com/a/33129119/2627768

huangapple
  • 本文由 发表于 2016年8月25日 02:27:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/39130567.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定