减少从浏览器发送到服务器的对象数据的最佳方法

use*_*858 4 javascript compression json

我们将以下数据从浏览器发送到服务器,除了 JSON 之外,序列化/反序列化数据的最佳方法是什么?

我们最初将数据保存在客户端浏览器中,并在定期检查点将其发送到服务器。由于数据的大小,发送数据时会占用大量浏览器内存和网络。我们希望减少发送到服务器的数据的大小,keys因为每个对象的数据大多相同,但会values发生变化。

[
   {
      "range":{
         "sLineNumber":3,
         "sColumn":3,
         "eLineNumber":3,
         "eColumn":3
      },
      "rLength":0,
      "text":"\n",
      "rOffset":4,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":4,
         "sColumn":1,
         "eLineNumber":4,
         "eColumn":1
      },
      "rLength":0,
      "text":"\n",
      "rOffset":5,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":5,
         "sColumn":1,
         "eLineNumber":5,
         "eColumn":1
      },
      "rLength":0,
      "text":"\n",
      "rOffset":6,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":1,
         "eLineNumber":6,
         "eColumn":1
      },
      "rLength":0,
      "text":"f",
      "rOffset":7,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":2,
         "eLineNumber":6,
         "eColumn":2
      },
      "rLength":0,
      "text":"a",
      "rOffset":8,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":3,
         "eLineNumber":6,
         "eColumn":3
      },
      "rLength":0,
      "text":"s",
      "rOffset":9,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":4,
         "eLineNumber":6,
         "eColumn":4
      },
      "rLength":0,
      "text":"d",
      "rOffset":10,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":5,
         "eLineNumber":6,
         "eColumn":5
      },
      "rLength":0,
      "text":"f",
      "rOffset":11,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":6,
         "eLineNumber":6,
         "eColumn":6
      },
      "rLength":0,
      "text":"a",
      "rOffset":12,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":7,
         "eLineNumber":6,
         "eColumn":7
      },
      "rLength":0,
      "text":"s",
      "rOffset":13,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":8,
         "eLineNumber":6,
         "eColumn":8
      },
      "rLength":0,
      "text":"f",
      "rOffset":14,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":9,
         "eLineNumber":6,
         "eColumn":9
      },
      "rLength":0,
      "text":"s",
      "rOffset":15,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":10,
         "eLineNumber":6,
         "eColumn":10
      },
      "rLength":0,
      "text":"a",
      "rOffset":16,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":11,
         "eLineNumber":6,
         "eColumn":11
      },
      "rLength":0,
      "text":"f",
      "rOffset":17,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":12,
         "eLineNumber":6,
         "eColumn":12
      },
      "rLength":0,
      "text":"s",
      "rOffset":18,
      "rMoveMarkers":false
   }
]
Run Code Online (Sandbox Code Playgroud)

我们思考的方法之一是将它们作为没有键的数组发送,因为我们知道每个key. 不确定是否有任何包可用于此转换。

Tom*_*aas 5

我们希望减少发送到服务器的数据的大小,keys因为每个对象的数据大多相同,但会values发生变化。

如果将数据视为表格,则可以将每一列表示为对象属性,行值在数组中,如下所示:

{
  "sLineNumber": [3, 4,         /* ... */ ],
  "sColumn":     [3, 1,         /* ... */ ],
  "eLineNumber": [3, 4,         /* ... */ ],
  "eColumn":     [3, 1,         /* ... */ ],
  "rLength":     [0, 0,         /* ... */ ],
  "text":        ["\n", "\n",   /* ... */ ],
  "rOffset":     [4, 5,         /* ... */ ],
  "rMoveMarkers":[false, false, /* ... */ ]
}
Run Code Online (Sandbox Code Playgroud)

此结构保留所有属性名称(除了"range")并且内存效率更高。

数据仍然可以序列化为 JSON,大小仅为原始结构的 25% 左右。

你可以得到使用整数(附加的尺寸缩减10替代布尔()truefalse中)"rMoveMarkers"

以下代码段中用于重组数据的快速而肮脏的代码:

var data = [
   {
      "range":{
         "sLineNumber":3,
         "sColumn":3,
         "eLineNumber":3,
         "eColumn":3
      },
      "rLength":0,
      "text":"\n",
      "rOffset":4,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":4,
         "sColumn":1,
         "eLineNumber":4,
         "eColumn":1
      },
      "rLength":0,
      "text":"\n",
      "rOffset":5,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":5,
         "sColumn":1,
         "eLineNumber":5,
         "eColumn":1
      },
      "rLength":0,
      "text":"\n",
      "rOffset":6,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":1,
         "eLineNumber":6,
         "eColumn":1
      },
      "rLength":0,
      "text":"f",
      "rOffset":7,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":2,
         "eLineNumber":6,
         "eColumn":2
      },
      "rLength":0,
      "text":"a",
      "rOffset":8,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":3,
         "eLineNumber":6,
         "eColumn":3
      },
      "rLength":0,
      "text":"s",
      "rOffset":9,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":4,
         "eLineNumber":6,
         "eColumn":4
      },
      "rLength":0,
      "text":"d",
      "rOffset":10,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":5,
         "eLineNumber":6,
         "eColumn":5
      },
      "rLength":0,
      "text":"f",
      "rOffset":11,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":6,
         "eLineNumber":6,
         "eColumn":6
      },
      "rLength":0,
      "text":"a",
      "rOffset":12,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":7,
         "eLineNumber":6,
         "eColumn":7
      },
      "rLength":0,
      "text":"s",
      "rOffset":13,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":8,
         "eLineNumber":6,
         "eColumn":8
      },
      "rLength":0,
      "text":"f",
      "rOffset":14,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":9,
         "eLineNumber":6,
         "eColumn":9
      },
      "rLength":0,
      "text":"s",
      "rOffset":15,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":10,
         "eLineNumber":6,
         "eColumn":10
      },
      "rLength":0,
      "text":"a",
      "rOffset":16,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":11,
         "eLineNumber":6,
         "eColumn":11
      },
      "rLength":0,
      "text":"f",
      "rOffset":17,
      "rMoveMarkers":false
   },
   {
      "range":{
         "sLineNumber":6,
         "sColumn":12,
         "eLineNumber":6,
         "eColumn":12
      },
      "rLength":0,
      "text":"s",
      "rOffset":18,
      "rMoveMarkers":false
   }
];

function transform(data){
  var transformed = {};
  ['rLength', 'text', 'rOffset', 'rMoveMarkers']
    .map(x => transformed[x] = data.map(y => y[x]));
  ['sLineNumber', 'sColumn', 'eLineNumber', 'eColumn']
    .map(x => transformed[x] = data.map(y => y.range[x]));
  return transformed;
}

var originalLength = JSON.stringify(data).length;
var transformedLength = JSON.stringify(transform(data)).length;

console.log(
  'Reduced to ' + 
  (100 * transformedLength / originalLength).toFixed(1) + 
  '% size of original, from ' + originalLength + ' characters to ' + 
  transformedLength + ' characters.'
);
console.log(transform(data));
Run Code Online (Sandbox Code Playgroud)

我们思考的方法之一是将它们作为没有键的数组发送,因为我们知道每个key. 不确定是否有任何包可用于此转换。

可以像这样将数据减少到二维数组:

function transform(data) {
  return ['rLength', 'text', 'rOffset', 'rMoveMarkers']
    .map(x => data.map(y => y[x]))
    .concat(
      ['sLineNumber', 'sColumn', 'eLineNumber', 'eColumn']
      .map(x => data.map(y => y.range[x]))
    );
}
Run Code Online (Sandbox Code Playgroud)

请注意,与上面的数据结构相比,删除键(属性名称)只会略微减少,同时它使跟踪错误或解决任何问题变得更加困难,因为您必须确保不会意外混淆哪个数组属于到哪个键。

以下代码段中的演示代码:

var data = [{
    "range": {
      "sLineNumber": 3,
      "sColumn": 3,
      "eLineNumber": 3,
      "eColumn": 3
    },
    "rLength": 0,
    "text": "\n",
    "rOffset": 4,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 4,
      "sColumn": 1,
      "eLineNumber": 4,
      "eColumn": 1
    },
    "rLength": 0,
    "text": "\n",
    "rOffset": 5,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 5,
      "sColumn": 1,
      "eLineNumber": 5,
      "eColumn": 1
    },
    "rLength": 0,
    "text": "\n",
    "rOffset": 6,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 1,
      "eLineNumber": 6,
      "eColumn": 1
    },
    "rLength": 0,
    "text": "f",
    "rOffset": 7,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 2,
      "eLineNumber": 6,
      "eColumn": 2
    },
    "rLength": 0,
    "text": "a",
    "rOffset": 8,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 3,
      "eLineNumber": 6,
      "eColumn": 3
    },
    "rLength": 0,
    "text": "s",
    "rOffset": 9,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 4,
      "eLineNumber": 6,
      "eColumn": 4
    },
    "rLength": 0,
    "text": "d",
    "rOffset": 10,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 5,
      "eLineNumber": 6,
      "eColumn": 5
    },
    "rLength": 0,
    "text": "f",
    "rOffset": 11,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 6,
      "eLineNumber": 6,
      "eColumn": 6
    },
    "rLength": 0,
    "text": "a",
    "rOffset": 12,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 7,
      "eLineNumber": 6,
      "eColumn": 7
    },
    "rLength": 0,
    "text": "s",
    "rOffset": 13,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 8,
      "eLineNumber": 6,
      "eColumn": 8
    },
    "rLength": 0,
    "text": "f",
    "rOffset": 14,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 9,
      "eLineNumber": 6,
      "eColumn": 9
    },
    "rLength": 0,
    "text": "s",
    "rOffset": 15,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 10,
      "eLineNumber": 6,
      "eColumn": 10
    },
    "rLength": 0,
    "text": "a",
    "rOffset": 16,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 11,
      "eLineNumber": 6,
      "eColumn": 11
    },
    "rLength": 0,
    "text": "f",
    "rOffset": 17,
    "rMoveMarkers": false
  },
  {
    "range": {
      "sLineNumber": 6,
      "sColumn": 12,
      "eLineNumber": 6,
      "eColumn": 12
    },
    "rLength": 0,
    "text": "s",
    "rOffset": 18,
    "rMoveMarkers": false
  }
];

function transform(data) {
  return ['rLength', 'text', 'rOffset', 'rMoveMarkers']
    .map(x => data.map(y => y[x]))
    .concat(
      ['sLineNumber', 'sColumn', 'eLineNumber', 'eColumn']
      .map(x => data.map(y => y.range[x]))
    );
}

var originalLength = JSON.stringify(data).length;
var transformedLength = JSON.stringify(transform(data)).length;

console.log(
  'Reduced to ' +
  (100 * transformedLength / originalLength).toFixed(1) +
  '% size of original, from ' + originalLength + ' characters to ' +
  transformedLength + ' characters.'
);
console.log(transform(data));
Run Code Online (Sandbox Code Playgroud)