json数据格式在网络中传输需要的数据比二进制庞大太多,我们可以省去key,外加将数字不需要编码成字符串,直接二进制编码就OK。

 

pack : 将json压包,unpack解包成json。

 

[javascript] view plain copy

 

1. var Struct = module.exports = {};  
2.   
3. Struct.TYPE = {  
4.     int8:1,  
5.     int16:2,  
6.     int32:3,  
7.     uint8:4,      
8.     uint16:5,  
9.     uint32:7,  
10.     string:8,  
11.     object:9,  
12.     aint8:10,  
13.     aint16:11,  
14.     aint32:12,  
15.     auint8:13,  
16.     auint16:14,  
17.     auint32:15,  
18.     aobject:16  
19. };  
20.   
21.   
22. //  
23. Struct.unpack = function(proto, buf) {  
24. var _unpack = function(proto, buf, pos) {  
25. var p = {};  
26. var ret;  
27. var length;  
28.   
29. for (var k in proto) {  
30. var type = proto[k][0];  
31. if (typeof type == 'object') {  
32. var json = type;  
33. 'object';  
34.             }  
35. if (proto[k].length == 2 && proto[k][1] == 'array') {  
36. 'a' + type;  
37.             }  
38. var value = [];  
39. switch(Struct.TYPE[type]) {  
40. case Struct.TYPE.int8:  
41.                     p[k] = buf.readInt8(pos);  
42.                     pos += 1;  
43. break;  
44. case Struct.TYPE.int16:  
45.                     p[k] = buf.readInt16BE(pos);  
46.                     pos += 2;  
47. break;  
48. case Struct.TYPE.int32:  
49.                     p[k] = buf.readInt32BE(pos);  
50.                     pos += 4;  
51. break;  
52. case Struct.TYPE.uint8:  
53.                     p[k] = buf.readUInt8(pos);  
54.                     pos += 1;  
55. break;  
56. case Struct.TYPE.uint16:  
57.                     p[k] = buf.readUInt16BE(pos);  
58.                     pos += 2;  
59. break;  
60. case Struct.TYPE.uint32:  
61.                     p[k] = buf.readUInt32BE(pos);  
62.                     pos += 4;  
63. break;  
64. case Struct.TYPE.string:  
65.                     ret = getLen(buf,pos);  
66.                     pos = ret[1];  
67. 'utf-8',pos, pos + ret[0]);  
68.                     pos += ret[0];  
69. break;  
70. case Struct.TYPE.object:  
71.                     ret = _unpack(json, buf, pos);  
72.                     p[k] = ret[0];  
73.                     pos = ret[1];  
74. break;  
75. case Struct.TYPE.aint8:  
76.                     ret = getLen(buf,pos);  
77.                     length = ret[0];  
78.                     pos = ret[1];  
79. for (var i=0; i < length; i++) {  
80.                         value.push(buf.readInt8(pos));  
81.                         pos += 1;  
82.                     }  
83.                     p[k] = value;  
84. break;  
85. case Struct.TYPE.aint16:  
86.                     ret = getLen(buf,pos);  
87.                     length = ret[0];  
88.                     pos = ret[1];  
89. for (var i=0; i < length; i++) {  
90.                         value.push(buf.readInt16BE(pos));  
91.                         pos += 2;  
92.                     }  
93.                     p[k] = value;  
94. break;  
95. case Struct.TYPE.aint32:  
96.                     ret = getLen(buf,pos);  
97.                     length = ret[0];  
98.                     pos = ret[1];  
99. for (var i=0; i < length; i++) {  
100.                         value.push(buf.readInt32BE(pos));  
101.                         pos += 4;  
102.                     }  
103.                     p[k] = value;                 
104. break;  
105. case Struct.TYPE.auint8:  
106.                     ret = getLen(buf,pos);  
107.                     length = ret[0];  
108.                     pos = ret[1];  
109. for (var i=0; i < length; i++) {  
110.                         value.push(buf.readUInt8(pos));  
111.                         pos += 1;  
112.                     }  
113.                     p[k] = value;  
114. break;  
115. case Struct.TYPE.auint16:  
116.                     ret = getLen(buf,pos);  
117.                     length = ret[0];  
118.                     pos = ret[1];  
119. for (var i=0; i < length; i++) {  
120.                         value.push(buf.readUInt16BE(pos));  
121.                         pos += 2;  
122.                     }  
123.                     p[k] = value;  
124. break;  
125. case Struct.TYPE.auint32:  
126.                     ret = getLen(buf,pos);  
127.                     length = ret[0];  
128.                     pos = ret[1];  
129. for (var i=0; i < length; i++) {  
130.                         value.push(buf.readUInt32BE(pos));  
131.                         pos += 4;  
132.                     }  
133.                     p[k] = value;  
134. break;  
135. case Struct.TYPE.astring:  
136.                     ret = getLen(buf,pos);  
137.                     length = ret[0];  
138.                     pos = ret[1];  
139. for (var i=0; i < length; i++) {  
140.                         ret = getLen(buf,pos);  
141.                         pos = ret[1];  
142. 'utf-8',pos, pos + ret[0]));  
143.                         pos += ret[0];  
144.                     }  
145.                     p[k] = value;  
146. break;  
147. case Struct.TYPE.aobject:  
148.                     ret = getLen(buf,pos);  
149.                     length = ret[0];  
150.                     pos = ret[1];  
151. for (var i=0; i < length; i++) {  
152.                         ret = _unpack(json, buf, pos);  
153.                         pos = ret[1];  
154.                         value.push(ret[0]);  
155.                     }  
156.                     p[k] = value;  
157. break;  
158.             }  
159.         }  
160.   
161. return [p,pos];  
162.     }  
163.   
164. return _unpack(proto, buf, 0)[0];  
165. }  
166.   
167. Struct.pack = function(proto, msg) {  
168. function _pack(proto, msg, buf, pos) {  
169. for (var k in proto) {  
170. var type = proto[k][0];  
171. if (typeof type == 'object') {  
172. var json = type;  
173. 'object';  
174.             }  
175. if (proto[k].length == 2 && proto[k][1] == 'array') {  
176. 'a' + type;  
177.             }  
178. switch(Struct.TYPE[type]) {  
179. case Struct.TYPE.int8:  
180.                     buf.writeInt8(msg[k], pos);  
181.                     pos += 1;  
182. break;  
183. case Struct.TYPE.int16:  
184.                     buf.writeInt16BE(msg[k], pos);  
185.                     pos += 2;  
186. break;  
187. case Struct.TYPE.int32:  
188.                     buf.writeInt32BE(msg[k],pos);  
189.                     pos += 4;  
190. break;  
191. case Struct.TYPE.uint8:  
192.                     buf.writeUInt8(msg[k], pos);  
193.                     pos += 1;  
194. break;  
195. case Struct.TYPE.uint16:  
196.                     buf.writeUInt16BE(msg[k],pos);  
197.                     pos += 2;  
198. break;  
199. case Struct.TYPE.uint32:  
200.                     buf.writeUInt32BE(msg[k], pos);  
201.                     pos += 4;  
202. break;  
203. case Struct.TYPE.string:  
204.                     pos = setLen(buf, msg[k].length, pos);  
205.                     buf.write(msg[k],pos);  
206.                     pos += msg[k].length;  
207. break;  
208. case Struct.TYPE.object:  
209.                     pos = _pack(json, msg[k], buf, pos);  
210. break;  
211.   
212. case Struct.TYPE.aint8:  
213. var list = msg[k];  
214.                     pos = setLen(buf, list.length, pos);  
215. for (var i=0; i < list.length; i++) {  
216.                         buf.writeInt8(list[i], pos++);  
217.                     }  
218. break;  
219. case Struct.TYPE.aint16:  
220. var list = msg[k];  
221.                     pos = setLen(buf, list.length, pos);  
222. for (var i=0; i < list.length; i++) {  
223.                         buf.writeInt16BE(list[i], pos);  
224.                         pos += 2;  
225.                     }  
226. break;  
227. case Struct.TYPE.aint32:  
228. var list = msg[k];  
229.                     pos = setLen(buf, list.length, pos);  
230. for (var i=0; i < list.length; i++) {  
231.                         buf.writeInt32BE(list[i], pos);  
232.                         pos += 4;  
233.                     }                     
234. break;  
235. case Struct.TYPE.auint8:  
236. var list = msg[k];  
237.                     pos = setLen(buf, list.length, pos);  
238. for (var i=0; i < list.length; i++) {  
239.                         buf.writeUInt8(list[i], pos++);  
240.                     }  
241. break;  
242. case Struct.TYPE.auint16:  
243. var list = msg[k];  
244.                     pos = setLen(buf, list.length, pos);  
245. for (var i=0; i < list.length; i++) {  
246.                         buf.writeUInt16BE(list[i], pos);  
247.                         pos += 2;  
248.                     }  
249. break;  
250. case Struct.TYPE.auint32:  
251. var list = msg[k];  
252.                     pos = setLen(buf, list.length, pos);  
253. for (var i=0; i < list.length; i++) {  
254.                         buf.writeUInt32BE(list[i], pos);  
255.                         pos +=4;  
256.                     }  
257. break;    
258. case Struct.TYPE.astring:  
259. var list = msg[k];  
260.                     pos = setLen(buf, list.length, pos);  
261. for (var i=0; i < list.length; i++) {  
262.                         pos = setLen(buf, list[i].length,pos);  
263.                         buf.write(list[i],pos);  
264.                         pos += list[i].length;  
265.                     }                     
266. break;  
267. case Struct.TYPE.aobject:  
268. var list = msg[k];  
269.                     pos = setLen(buf, list.length, pos);  
270. for (var i=0; i < list.length; i++) {  
271.                         pos = _pack(json, list[i], buf, pos);  
272.                     }  
273. break;  
274.             }  
275. //console.log('key: ' + k);  
276. //console.log('pos: ' + pos);  
277.         }  
278. return pos;  
279.     }  
280.   
281. var length = jsonSize(proto, msg);  
282. var buf = new Buffer(length);  
283.     _pack(proto, msg, buf, 0);  
284. return buf;  
285. };  
286.   
287.   
288. var jsonSize = function(proto, msg) {  
289. function _size(proto, msg) {  
290. var size = 0;  
291. var buf = new Buffer(4);  
292. for (var k in proto) {  
293. var type = proto[k][0];  
294. if (typeof type == 'object') {  
295. var json = type;  
296. 'object';  
297.             }  
298. if (proto[k].length == 2 && proto[k][1] == 'array') {  
299. 'a' + type;  
300.             }  
301. switch(Struct.TYPE[type]) {  
302. case Struct.TYPE.int8:  
303.                     size += 1;  
304. break;  
305. case Struct.TYPE.int16:  
306.                     size += 2;  
307. break;  
308. case Struct.TYPE.int32:  
309.                     size += 4;  
310. break;  
311. case Struct.TYPE.uint8:  
312.                     size += 1;  
313. break;  
314. case Struct.TYPE.uint16:  
315.                     size += 2;  
316. break;  
317. case Struct.TYPE.uint32:  
318.                     size += 4;  
319. break;  
320. case Struct.TYPE.string:  
321.                     size += setLen(buf, msg[k].length, 0);  
322.                     size += msg[k].length;  
323. break;  
324. case Struct.TYPE.object:  
325.                     size += _size(json, msg[k]);  
326. break;  
327. case Struct.TYPE.aint8:  
328. var list = msg[k];  
329.                     size += setLen(buf, list.length, 0);  
330.                     size += list.length;  
331. break;  
332. case Struct.TYPE.aint16:  
333. var list = msg[k];  
334.                     size += setLen(buf, list.length, 0);  
335.                     size += list.length * 2;  
336. break;  
337. case Struct.TYPE.aint32:  
338. var list = msg[k];  
339.                     size += setLen(buf, list.length, 0);  
340.                     size += list.length * 4;      
341. break;  
342. case Struct.TYPE.auint8:  
343. var list = msg[k];  
344.                     size += setLen(buf, list.length, 0);  
345.                     size += list.length;      
346. break;  
347. case Struct.TYPE.auint16:  
348. var list = msg[k];  
349.                     size += setLen(buf, list.length, 0);  
350.                     size += list.length * 2;      
351. break;  
352. case Struct.TYPE.auint32:  
353. var list = msg[k];  
354.                     size += setLen(buf, list.length, 0);  
355.                     size += list.length * 4;      
356. break;  
357. case Struct.TYPE.astring:  
358. var list = msg[k];  
359.                     size += setLen(buf, list.length, 0);  
360. for (var i=0; i < list.length; i++) {  
361.                         size += setLen(buf, list[i].length,0);  
362.                         size += list[i].length;  
363.                     }                     
364. break;  
365. case Struct.TYPE.aobject:  
366. var list = msg[k];  
367.                     size += setLen(buf, list.length, 0);  
368. for (var i=0; i < list.length; i++) {  
369.                         size += _size(json, list[i]);  
370.                     }  
371. break;  
372.             }  
373.         }  
374. return size;  
375.     }  
376. var size = 0;  
377.     size += _size(proto, msg);  
378. return size;  
379. }  
380.   
381. var MASK_7 = (1<<7) - 1;  
382. var MASK_8 = (1<<8) - 1;  
383. var MAX_LEN = (1<<28);  
384.   
385.   
386. //不定长记录长度,1-4个字节,和MQTT表示长度的方法相同  
387. var getLen = function(buf, pos) {  
388. var len = 0;  
389. for (var i = 0; i < 4; i++) {  
390. var value = buf.readUInt8(pos);  
391. //console.log('get: ' + value);  
392.         len += (value & MASK_7) << (7 * i);  
393.         pos += 1;  
394. if (value < 127) {   
395. break;  
396.         }  
397.     }  
398. return [len, pos];  
399. }  
400.   
401. var setLen = function(buf, len, pos) {  
402.   
403. while(len > 0) {  
404. var value = len & MASK_8;  
405.         len = len >> 7;  
406. if (len > 0) {  
407.             value = value | 128;  
408.         }  
409.         buf.writeUInt8(value, pos++);  
410.     }  
411. return pos;  
412. }

 

 

测试代码:

 

[javascript] view plain copy

 

1. var Struct = require('./struct');  
2.   
3. var proto = {  
4. 'int8'],  
5. 'int16'],  
6. 'int32'],  
7. 'uint8'],  
8. 'uint16'],  
9. 'uint32'],  
10. 'string'],  
11. 'int8', 'array'],  
12. 'int16', 'array'],  
13. 'int32', 'array'],  
14. 'uint8', 'array'],  
15. 'uint16', 'array'],  
16. 'uint32', 'array'],  
17.     object : [  
18. 'int8'], int16: ['int16'], string: ['string'], astring: ['astring']}  
19.     ],  
20.     aobject : [  
21. 'int8'], int16: ['int16'], string: ['string'], astring: ['astring']},  
22. 'array'  
23.     ],  
24. 'string', 'array']  
25. }  
26.   
27. var msg = {  
28.     int8   : 12,  
29.     int16  : 1234,  
30.     int32  : 12345,  
31. // > 128  
32. // >> 128 * 256  
33. // >> 3 * (1<<30)  
34. 'hello world',  
35.     aint8  : [-1, -2, -3, -5, -6],  
36.     aint16 : [-11, -12, -13, -15, -17],  
37.     aint32 : [-337, -338, -339, -3310, -3311],  
38.     auint8 : [1, 2, 3, 4],  
39.     auint16: [8, 9, 10, 11, 12],  
40.     auint32: [12, 13, 15, 16],  
41. 'somebady', astring: ['save me', 'Dont stop me now']},  
42. 'somebady', astring: ['save me', 'Dont stop me now']}, {int8: 12, int16: 1234, string: 'somebady', astring: ['save me', 'Dont stop me now']}],  
43. 'melo', 'kaka', 'much', 'save']  
44. }  
45.   
46.   
47. var buf = Struct.pack(proto, msg);  
48. console.log(buf);  
49.   
50. var remsg = Struct.unpack(proto, buf);  
51. console.log(JSON.stringify(remsg));