前言
本文将先容物联网范畴的JSON格式——CBOR,CBOR是专门为受限定物联网终端筹划的数据互换格式,该格式轻量轻便,可以简朴明白为二进制情势JSON格式。CBOR格式可以与COAP协议组合利用,如同HTTP+JSON;别的,CBOR也是COSE的根本。
CBOR简述
CBOR可分为8个主范例(Major Type),CBOR格式为了界说8种差别的范例,采取首字节的高3位界说主范例。 首字节的低5位在差别的主范例表现长度(除主范例0和主范例1),如果长度指示不敷,则依次利用后续字节。
主范例 |
名称 |
首字节 |
简朴阐明 |
主范例0 |
无符号整数 |
0x00或 0x10 |
根本范例 |
主范例1 |
负整数 |
0x20或 0x30 |
根本范例 |
主范例2 |
字节数组 |
0x40或 0x50 |
根本范例 |
主范例3 |
字符串 |
0x60或 0x70 |
根本范例 |
主范例4 |
数组 |
0x80或 0x90 |
组合范例,可嵌套恣意范例 |
主范例5 |
键值对 |
0xA0或 0xB0 |
组合范例,可嵌套恣意范例 |
主范例6 |
扩展 |
0xC0或 0xD0 |
扩展范例 |
主范例7 |
数组 |
0xE0或 0xF0 |
浮点数与简朴范例 |
无符号整数 an unsigned integer
主范例0 ,无符号整数编码后首字节为0b000_XXXXX。为了表达差别长度的无符号整数,CBOR格式利用第一个字节的低5位表现整数范例
- 0b000_11000 uint8_t
- 0b000_11001 uint16_t
- 0b000_11010 uint32_t
- 0b000_11011 uint64_t
请注意,无符号整数0到23直接表达,无需利用整数范例。
比方:
- 10 编码后 0x0A
- 24 编码后 0x1818
- 100 编码后 0x1864
- 1000 编码后 0x1903E8
负整数 a negative integer
主范例1 ,无符号整数编码后首字节为0b001_XXXXX。负整数的编码方式与无符号整数相似。
比方:
- -10 编码后 0x29
- -24 编码后 0x37
- -100 编码后 0x3863
- -1000 编码后 0x3903E7
字节数组 a byte string
主范例2 ,字节数组编码后首字节为0b010_XXXXX。为了表达字节数组长度,如果字符数组的长度小于即是23,那么直接利用首字节的低5位表现;如果长度大于或即是24字节,那么利用第二个字节表现长度;如果长度大于即是256字节,那么利用第二和第三个字节表现长度。
CBOR格式中一样寻常采取多字节组合的方式表达长度。CBOR如许的长度形貌方法便于嵌入式装备利用C语言分析CBOR格式,节流名贵的栈空间与堆空间。
比方:
- HEX格式01020304 编码后 0x4401020304
- 长度为23的字节数组 编码后 0x57XX…
- 长度为24的字节数组 编码后 0x5818XX…
- 长度为100的字节数组 编码后 0x5901F4XX…
本质来说,CBOR仅为这些原始的字节数组增长了一个长度形貌。
特别注意点
别的在CBOR格式编码钱的字节数组一样寻常采取采取小写h开头,在单引号中形貌HEX格式内容,比方
字符串 a text string
主范例3 。字符串范例编码后首字节为0b011_XXXXX。字符串格式与字节数组格式非常相似,只是字节数组格式人类不可读,而字符格式人类可读。字符串格式表达长度的方式与字节数组范例相似。
比方:
- “a” 编码后 0x6161
- “IETF” 编码后 0x6449455446
- 长度为24的字符串 编码后 0x781830XX…
数组 an array of data items
主范例4 。 数组编码后首字节为0b100_XXXXX。以上四种均为根本格式,而数组为一种符合,还可以与自身或其他范例嵌套。数组中数组元素个数(不是编码后字节长度)的表达方式与字节数组范例相似。
比方:
- [1,2,3] 编码后 0x83010203
- [1,[2,3], [4,5]] 编码后 0x8301820203820405,此处包罗3个数组,第一个数组0x83,表现元素个数为3,第二个0x82b表现元素个数为2,第3个编码后元素个数为3。
对于数组部门,RFC7049也有些表述不清的地方。在主范例无符号整数中,若整数值凌驾24(0x18),该值将会被CBOR编码为0x1818。
- [24, 25, 26] 编码后为 0x8318181819181A,不是0x83181818。
- [500, 501, 502] 编码后为0x831901F41901F51901F6,不是0x8301F401F501F6
特别注意点
在JSON范例中,键名Key必须为字符串,但是在CBOR格式中,键名Key可以是整数。CBOR通过这种方式可以节流物联网终端开销。
键值对 a map of pairs of data items
主范例5 。键值对编码后首字节为0b101_XXXXX。键值对也是一种符合范例,可以嵌套恣意范例。键值对范例中键值对个数(不是编码后的字节长度)的表达方式与字节范例表达方式相似。比方
- {“a”:1, “b”:[2,3]} 编码后 0xA26161016162820203, 此中0x616101中 0x616101表现一个键值对,0x6161表现字符串编码"a", 0x01表现值1。此中0x6162820203表现另一个键值对,0x6162表现字符串编码"b",0x820203表现一个数组。
- {1:2, 3:4} 编码后 0xA201020304 (还须要分析,JSON中键名不能为数字,而CBOR可以)
扩展范例
主范例6 。扩展范例编码后首字节为0b110_XXXXX。CBOR通过增长Tag的方式扩展范例,满意未来的扩展。COSE规范中通过CBOR Tag界说了多种新范例。本文暂不详细睁开扩展范例,仅给出几个CBOR示例
- 23(h’01020304’) 编码后 0xd74401020304
特别阐明
在CBOR扩展类范例形貌中,一样寻常以Tag编号开头,然后在小括号中()生存内容,内容可以是恣意一种CBOR范例。
浮点数与简朴范例
主范例7 。浮点数与简朴范例编码后首字节为0b111_XXXXX。该范例界说了简朴范例,时间范例(Date和Time)、大整数(Bignum),10进制整数(Decimal)等。在主范例7中,首字节的高3位固定为0b111,首字节中低5位用于表现子范例。
简朴范例
首字节的低5位中0到23表现简朴类,界说如下:
- 20 表达False
- 21 表达True
- 22 表达Null
- 23 表达Undefined Value
以是
- False 编码后 0xF4
- True 编码后 0xF5
- Null 编码后 0xF6
时间范例
CBOR体验
参考依赖
com.upokecenter
cbor
4.0.0-alpha2
还依赖了两个参考库joda-time 和hexdump
org.lasinger.tools
hexdump
0.2.0
joda-time
joda-time
2.10.2
整数相干
@Test
public void testInt() {
CBORObject obj = CBORObject.FromObject(1);
// 通过控制台打印
byte[] bytes = obj.EncodeToBytes();
String hexString = Hexdump.hexdump(bytes);
System.out.println(hexString);
}
@Test
public void testInt100() {
CBORObject obj = CBORObject.FromObject(100);
// 通过控制台打印,打印方法省略
}
@Test
public void testIntNegative100() {
CBORObject obj = CBORObject.FromObject(-100);
// 通过控制台打印,打印方法省略
}
字节数组与字符串
@Test
public void testByteArray() {
int length = 500;
byte[] testByte = new byte[length];
for (int i = 0; i < length; i++) {
testByte[i] = 0x30;
}
CBORObject obj = CBORObject.FromObject(testByte);
// 通过控制台打印,打印方法省略
}
@Test
public void testString() {
CBORObject obj = CBORObject.FromObject("IETF");
// 通过控制台打印,打印方法省略
}
@Test
public void testLargeString() {
int length = 24;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; i++) {
builder.append("0");
}
CBORObject obj = CBORObject.FromObject(builder.toString());
// 通过控制台打印,打印方法省略
}
数组
@Test
public void testArray() {
CBORObject obj = CBORObject.NewArray();
obj.Add(CBORObject.FromObject(1));
obj.Add(CBORObject.FromObject(2));
obj.Add(CBORObject.FromObject(3));
// 通过控制台打印,打印方法省略
}
@Test
public void testArray24() {
CBORObject obj = CBORObject.NewArray();
obj.Add(CBORObject.FromObject(500));
obj.Add(CBORObject.FromObject(501));
obj.Add(CBORObject.FromObject(502));
// 通过控制台打印,打印方法省略
}
/**
* 嵌套数组 [1, [2,3], [4,5]]
*/
@Test
public void testMultiArray() {
CBORObject obj = CBORObject.NewArray();
obj.Add(CBORObject.FromObject(1));
CBORObject subArray1 = CBORObject.NewArray();
subArray1.Add(CBORObject.FromObject(2));
subArray1.Add(CBORObject.FromObject(3));
obj.Add(subArray1);
CBORObject subArray2 = CBORObject.NewArray();
subArray2.Add(CBORObject.FromObject(4));
subArray2.Add(CBORObject.FromObject(5));
obj.Add(subArray2);
// 通过控制台打印,打印方法省略
}
@Test
public void testLargeArray() {
CBORObject obj = CBORObject.NewArray();
int length = 25;
for (int i = 0; i < length; i++) {
int temp = i + 100;
obj.Add(CBORObject.FromObject(temp));
}
// 通过控制台打印,打印方法省略
}
键值对
@Test
public void testMap() {
CBORObject obj = CBORObject.NewMap();
obj.set(1, CBORObject.FromObject(2));
obj.set(3, CBORObject.FromObject(4));
// 通过控制台打印,打印方法省略
}
@Test
public void testJavaMap() {
Map map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
CBORObject obj = CBORObject.FromObject(map);
// 通过控制台打印,打印方法省略
}
浮点型和简朴范例
@Test
public void testTrue() {
CBORObject obj = CBORObject.FromObject(true);
byte[] bytes = obj.EncodeToBytes();
String hexString = Hexdump.hexdump(bytes);
System.out.println(hexString);
}
@Test
public void testBigDecimal() {
String decimalString = BigDecimal.valueOf(273.15).toString();
CBORObject obj = CBORObject.FromObject(EDecimal.FromString(decimalString));
// 通过控制台打印,打印方法省略
}
@Test
public void testDateTime() {
DateTime dt = new DateTime(2013, 3, 21, 20, 04, 0);
CBORObject obj = CBORObject.FromObject(dt.toDate());
// 通过控制台打印,打印方法省略
}
扩展范例
@Test
public void testCBORTag() {
byte[] array = new byte[] {0x01, 0x02, 0x03, 0x04};
CBORObject obj = CBORObject.FromObjectAndTag(array, 23);
System.out.println(obj.toString());
byte[] bytes = obj.EncodeToBytes();
String hexString = Hexdump.hexdump(bytes);
System.out.println(hexString);
}
总结
- CBOR格式是一种带有显着长度指示的传输协议,而常用的JSON格式并没有长度指示。长度指示可以资助终端装备在举行CBOR分析时节流名贵的堆空间。
- CBOR格式支持键值对情势 Key-Value,Key可以是整数,而JSON格式中Key值只能是字符串。
- CBOR格式中Date、Time、Decimal范例办理了物联网终端装备中时间日期与十进制数表达的标题。
参考资料
- 【RFC7049 Concise Binary Object Representation (CBOR)】
- 【示例代码】
! |