目的
了解mongodb java驱动如何和mongod作数据交互,同时了解object json bson的数据格式解析过程
概述
mongodb采用的java转json是使用自定义的方法:com.mongodb.util.JSON类来处理;
转json:public static String serialize(Object o)
反转json:public static Object parse(String s)
那就看看这两个方法的具体实现
java object to json
mongodb java客户端的对象主要是DBObject及其之类,采用递归方式处理嵌套关系,我们也可以从中学习到如何将一个对象转为string类型的其他格式。
类型 | 转化方式 |
Null类型: | 字符串 null |
Boolean类型:对应的值 | true False |
Number类型: Byte Short Integer Long Float Double BigInteger BigDecimal AutomicInteger AutomicLong | 返回对应数值的字符串 |
String类型: 这里的string类型主要是DBObject的key, 对于mongodb,DBObject的key为{“key”,...}这种格式, 因此要对特殊字符作处理,目前处理如下 | \ -> \\ “ -> \* \n -> \\n \r -> \\r \t -> \\t \b -> \\b ASCII为32之前的字符都忽略,这些是控制字符 举例: abc -> “abc” “abc -> “\”abc” a\b”c -> “a\\b\”c” |
ObjectId类型: 对于ObjectId类型,先转成BasicDBObject方式再进行解析 {“$oid”, objectId.toString()} | 如objectId为:789dsab4adafasdfsdfasdf873294 {“$oid” : 789dsab4adafasdfsdfasdf873294} |
Iterable类型: 对于迭代起类型,递归调用每个类型进行处理 | 字符迭代器:[abc, bcd, cde, def ] DBObject迭代器:[{“abc”, value}, {“bcd”, value }, {“cde”, def} ] |
DBObject类型: 根据简单类型递归处理 | 转成形如: {key:{key,value}, key:value} |
Map类型: 这个基本不用想了,因为DBObject本身就继承自map, 所以map的解析和DBObject一致 | 同上 |
Date类型: | {“$date”, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"} |
DBRefBase类型: 转成DBObject | {”$ref”, ref.getRef(), “$id”, ref.getId()} |
byte[]或者Binary: | <Binary Data> |
数组类型: | [“key”:”value”, “key”:”value”] |
Pattern类型: 转DBObject | {"$regex": o.toString(), $options: Bytes.regexFlags(((Pattern) o).flags())} |
BSONTimestamp类型: 转DBObject | {“$ts”:t.getTime(), “$inc”:t.getInc()} |
UUID类型: 转DBObject | {"$uuid":uuid.toString()} |
CodeWScope类型: 转DBObject | {"$code":c.getCode(), "$scope": c.getScope()} |
Code类型: 转DBObject | {"$code":c.getCode()} |
MinKey类型: 转DBObject | {$minKey":1} |
MaxKey类型: 转DBObject | {"$maxKey":1} |
json to java object
处理的内容比较明确:
null
NaN
true
false
字符串类型 \' \"
数字类型 0 - 9 + -
数组类型
对象
以上讨论针对的是java对象转成json对象,接下去讨论json对象转化为bson对象。
这方面的内容bson连接讨论的比较详细,url为:http://bsonspec.org/#/specification
不过看了这个文档1个小时后终于把这个文档的两个事例看懂,因此有必要在这里说明下,以便其他观看文档的人更容易理解
json to bson
还是现来看一下文档中提到的两个例子。
先看第一个
{"hello": "world"}
按格式规范转应该是如下内容:
int32 -- 指定文档大小,包括结尾的\x00
\x02 (byte*) \x00 -- 一个字符标明value的类型,接着是key字符串的byte值,最后以\x00结束
int32 (byte*) \x00 -- int32是value btye大小加上\x00的长度,接着是value的具体值,最后以\x00结尾
\x00 -- \x00结尾
对应的具体形式:
\x16\x00\x00\x00 -- 本文档总字节数为22
\x02 hello \x00 -- value类型为string类型 key的值为hello
\x06\x00\x00\x00 world \x00 -- value字节数为6(包括结尾的\x00) value值为world
\x00 -- 文档结束
这样一划分,结构就清晰多了
以上简单格式解析基本能对应上,再来看第二个例子:
{"BSON": ["awesome", 5.05, 1986]}
还是先转成通用格式,这里说明下array在bson中是一个内嵌文档,格式如下{0:array[0], 1:array[1], 2:array[2]}:
int32 -- 文档大小
\x04 (byte*) \x00 -- value类型 key值 结束符
int32 -- 内嵌文档大小
\x02 (byte*) \x00 -- value类型 key值 结束符
int32 (byte*) \x00 -- string大小 value值 结束符
\x01 (byte*) \x00 -- value类型 key值 结束符
double -- value值
\x10 (byte*) \x00 -- value类型 key值 结束符
int32 -- value值
\x00
\x00
对应的具体形式:
"1\x00\x00\x00 -- 文档大小为49,这里的1是ascii值
\x04 BSON \x00 -- value为array类型,key值为bson
&\x00\x00\x00 -- 内嵌文档大小为38
\x02 0 \x00 -- value值的类型为string, key的值为0
\x08\x00\x00\x00 awesome \x00 -- string大小为8个字节, 值为awesome
\x01 1 \x00 -- value为double类型,key值为1
333333\x14@ -- 5.05对应的byte[]值,大小为8B,先调用Double.doubleToRawLongBits( x ),再以long方式写入。
\x10 2 \x00 -- value为32位整型,key值为2
\xc2\x07\x00\x00 -- 4B的值,echo $((12*16 + 2 + 7*16*16)),低位在前,高位在后
\x00
\x00"
以上两个列子基本上能了解如何把一个json对象转成bson对象了,这样在wireshark协议时基本上也没什么问题。
bson to json
1.如何判断key,value编码方式:
每字节读取,分析字节是否为[0,127];是:表示为纯英文;如果有一个字符不为这个范围内的字符,表示包含其他字符方式,采用utf-8方式解码
2.
后续继续更新上去,可直接看mongodb源代码
https://github.com/michel-kraemer/bson4jackson