0

我需要在我的 MongoDB 集合中保留一些二进制数据。在使用 C++ 驱动程序或 Java 驱动程序检索相同记录时,似乎我的文档得到了不同的 JSON 表示。这是一个例子。使用 Mongo shell 在 MongoDB 集合中插入三条记录:

db.binary_test.insert({"name":"Alex", "data" :BinData("0x00", "12345678")})
db.binary_test.insert({"name":"Alex", "data" :BinData("0x80", "12345678")}) 

第一条记录使用二进制类型 0x00(通用);第二个 - 0x80(用户定义)。

使用 Mongo Shell 检索这些记录:

db.binary_test.find().pretty()

输出:

{
    "_id" : ObjectId("51acf66886174308b610d950"),
    "name" : "Alex",
    "data" : BinData(0,"12345678")
}
{
    "_id" : ObjectId("51acf66c86174308b610d951"),
    "name" : "Alex",
    "data" : BinData(128,"12345678")
}

请注意,标签表示为数字,而不是十六进制字符串。

现在使用一个非常简单的 Java 程序检索相同的记录,并使用严格的序列化程序将它们转换为 JSON:

ObjectSerializer serializer = JSONSerializers.getStrict();
System.out.println(serializer.serialize(doc));

这是输出:

{ "_id" : { "$oid" : "51acf66886174308b610d950"} , "name" : "Alex" , "data" : { "$binary" : "12345678" , "$type" : 0}}
{ "_id" : { "$oid" : "51acf66c86174308b610d951"} , "name" : "Alex" , "data" : { "$binary" : "12345678" , "$type" : -128}}

请注意,二进制数据类型表示为整数,而不是十六进制字符串。

现在为了比较使用 MongoDB C++ 驱动程序来检索相同的两条记录并使用该jsonString()方法打印它们。这是输出:

{ "_id" : { "$oid" : "51acf66886174308b610d950" }, "name" : "Alex", "data" : { "$binary" : "12345678", "$type" : "00" } }
{ "_id" : { "$oid" : "51acf66c86174308b610d951" }, "name" : "Alex", "data" : { "$binary" : "12345678", "$type" : "80" } }

现在类型是十六进制字符串,而不是数字。

因此,同一记录具有不同的 JSON 表示,具体取决于它是使用 C++ 驱动程序还是 Java 驱动程序检索的。当一些软件使用 Java 驱动程序而一些软件使用 C++ 驱动程序时,这种差异会在混合环境中产生问题。有什么建议如何解决问题(除了更改驱动程序代码)?哪一个是正确的 - 将类型表示为十六进制字符串的 C++ 驱动程序,还是 Java 驱动程序?我的理解是 C++ 驱动程序返回的表示是正确的,但有人可以证实这一点吗?

MongoDB http 接口还返回十六进制字符串表示 - 可能是因为支持 REST 接口 (mongod) 的后端是用 C++ 编写的。

我正在使用 Java 驱动程序版本 2.11.1 和 C++ 驱动程序版本 2.4.3。

4

2 回答 2

0

这是 Java 驱动程序中的一个错误

于 2013-06-06T22:29:41.543 回答
0

这里没有区别。数据是相同的,只有使其人类可读的格式化程序以不同的格式呈现。

jsonString()[...] 使用方法打印它们

这就是重点,您查看格式化输出:“0x80”、“80”、128 和 -128都可以表示相同的意思。数据总是根据某种约定进行解释。在“0x80”的情况下,“0x”前缀是一种用于表示十六进制表示法的普遍惯例。“80”要求您知道数据应被解释为十六进制字符串,对应二进制值 1000000,对于整数,等于十进制值 128。但是,如果该值被解释为byte,则它对应到-128。

您的代码不应查看格式化的输出,而应与具有明确定义类型的字段或属性进行比较,例如int. 然后,你可以写

if(a.Type == 128) { ... }

无论您的编程语言的格式化程序输出什么,哪个应该评估为正确的值。(如果a.Typebyte,则必须与 -128 进行比较。如果与 128 进行比较,大多数编程语言都会发出警告或错误,因为 128 大于最大可表示的有符号 8 位值,即字节)。

顺便说一句,当您查看对象 id 的表示形式时,不同的格式更加引人注目:在 mongo 控制台中,它显示为ObjectId("51acf66886174308b610d950"),C++ json 格式化程序显示"_id" : {"$oid" : "51acf66886174308b610d950"}. 同样,它是相同的数据,但这里的字符串看起来相同,而它周围的脚手架看起来不同。

于 2013-06-04T14:47:31.113 回答