【转】参照protobuf,将json数据转换成二进制在网络中传输。

http://blog.csdn.net/gamesofsailing/article/details/38335753?utm_source=tuicool&utm_medium=referral

 

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

 

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

 

[javascript] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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.                 type = 'object';  
  34.             }  
  35.             if (proto[k].length == 2 && proto[k][1] == 'array') {  
  36.                 type = '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.                     p[k] = buf.toString('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.                         value.push(buf.toString('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.                 type = 'object';  
  174.             }  
  175.             if (proto[k].length == 2 && proto[k][1] == 'array') {  
  176.                 type = '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.                 type = 'object';  
  297.             }  
  298.             if (proto[k].length == 2 && proto[k][1] == 'array') {  
  299.                 type = '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
 
 在CODE上查看代码片派生到我的代码片
  1. var Struct = require('./struct');  
  2.   
  3. var proto = {  
  4.     int8   : ['int8'],  
  5.     int16  : ['int16'],  
  6.     int32  : ['int32'],  
  7.     uint8  : ['uint8'],  
  8.     uint16 : ['uint16'],  
  9.     uint32 : ['uint32'],  
  10.     string : ['string'],  
  11.     aint8  : ['int8', 'array'],  
  12.     aint16 : ['int16', 'array'],  
  13.     aint32 : ['int32', 'array'],  
  14.     auint8 : ['uint8', 'array'],  
  15.     auint16: ['uint16', 'array'],  
  16.     auint32: ['uint32', 'array'],  
  17.     object : [  
  18.         {int8: ['int8'], int16: ['int16'], string: ['string'], astring: ['astring']}  
  19.     ],  
  20.     aobject : [  
  21.         {int8: ['int8'], int16: ['int16'], string: ['string'], astring: ['astring']},  
  22.         'array'  
  23.     ],  
  24.     astring: ['string', 'array']  
  25. }  
  26.   
  27. var msg = {  
  28.     int8   : 12,  
  29.     int16  : 1234,  
  30.     int32  : 12345,  
  31.     uint8  : 130,// > 128  
  32.     uint16 : 32800, // >> 128 * 256  
  33.     uint32 : 3221245472, // >> 3 * (1<<30)  
  34.     string : '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.     object : {int8: 12, int16: 1234, string: 'somebady', astring: ['save me', 'Dont stop me now']},  
  42.     aobject : [{int8: 12, int16: 1234, string: 'somebady', astring: ['save me', 'Dont stop me now']}, {int8: 12, int16: 1234, string: 'somebady', astring: ['save me', 'Dont stop me now']}],  
  43.     astring: ['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));  

posted on 2016-05-06 17:26  mimime  阅读(1075)  评论(0编辑  收藏  举报