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));