Home > database >  What is a size efficient way to encode a JSON array of array of numbers into a URL
What is a size efficient way to encode a JSON array of array of numbers into a URL

Time:07-25

I have an array of array of numbers as data:

[[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360],
[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360]]

I can import this data into my app and load the state.

So I want to encode this into a URL so it's easier to share.

What is the most size efficient way to encode this data into a URL.

Also acceptable is any reliable third party services that I can save/load my state from, like github gist or something.

CodePudding user response:

Ok, so base64 is not for compression. But I just (re)invented a compression method and base64 is part of it. It compress to about 65% indeed. The idea is to compress each pair of digits to a 2 digit hex number which is one ascii char. Then base64 it for safety.

var data = [
  [0.3, 2.1, -0.04, 32, 0, 54],
  [9, 593, 82, 593, 1360, 593, 82, 582, 1344, 4676, 1344, 593, 82, 593, 82, 578, 1344, 593, 82, 577, 1344, 593, 82, 567, 1328, 593, 82, 4662, 1328, 593, 82, 4662, 1328, 593, 82, 577, 1344, 593, 82, 4674, 1344, 582, 1344, 594, 1360, 4693, 1360, 599, 1360, 4705, 1376, 582, 1344, 581, 1344, 581, 1344, 4677, 1344, 4678, 1344, 593, 1360, 4690, 1360],
  [9, 593, 82, 593, 1360, 593, 82, 582, 1344, 4676, 1344, 593, 82, 593, 82, 578, 1344, 593, 82, 577, 1344, 593, 82, 567, 1328, 593, 82, 4662, 1328, 593, 82, 4662, 1328, 593, 82, 577, 1344, 593, 82, 4674, 1344, 582, 1344, 594, 1360, 4693, 1360, 599, 1360, 4705, 1376, 582, 1344, 581, 1344, 581, 1344, 4677, 1344, 4678, 1344, 593, 1360, 4690, 1360],
];


function encode_char(c) {
  if (c == '[') return 'a';
  if (c == ']') return 'b';
  if (c == ',') return 'c';
  if (c == ' ') return 'd';
  if (c == '.') return 'e';
  if (c == '-') return 'f';
  return ""   c;
}


function decode_char(c) {
  if (c == 'a') return '[';
  if (c == 'b') return ']';
  if (c == 'c') return ',';
  if (c == 'd') return ' ';
  if (c == 'e') return '.';
  if (c == 'f') return '-';
  return ""   c;
}

function encode_string(str) {
  var result = "";
  var arr = str.split("");
  if (arr.length % 2) {
    arr.push(" ")
  }
  for (var i = 0; i < arr.length; i  = 2) {
    var c1 = encode_char(arr[i])
    var c2 = encode_char(arr[i   1])
    var hex = ""   c1   c2
    result  = String.fromCharCode(parseInt(hex, 16));
  }
  return result;
}

function decode_string(str) {
  var result = "";
  var arr = str.split("");
  for (var i = 0; i < arr.length; i  = 1) {
    var char = arr[i]
    var hex = char.charCodeAt(0).toString(16);
    hex = hex.length < 2 ? "0"   hex : hex;
    var c1 = decode_char(hex.slice(0, 1))
    var c2 = decode_char(hex.slice(1, 2))
    result  = ""   c1   c2
  }
  return result.trim();
}

function encode_integers(str) {
  var result
  result = encode_string(str);
  result = btoa(result)
  result = encodeURIComponent(result)
  return result;
}

function decode_integers(str) {
  var result
  result = decodeURIComponent(str);
  result = atob(result)
  result = decode_string(result)
  return result;
}

var json = JSON.stringify(data);
console.log(json.length, json)

var str = encode_integers(json);
console.log(str.length, str)

var json = decode_integers(str)
console.log(json.length, json)

console.log("compression ratio", (str.length / json.length).toFixed(2))

CodePudding user response:

You can use compression and decompression methods to reduce the size of the input by ~ 65% to encode it in the URL

first I stringify the input then encrypt it

I also attached the description method


You can also find more efficient compression algorithms than this.

ex:

e1 <== slightly more efficient than the one I wrote

e2 <== gzip implementation

const input = [[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360],
[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360]]

let firstStep = JSON.stringify(input)


let secondStep = en(firstStep);

console.log("The original input lost: "   (1-(secondStep.length / firstStep.length))  " % of it's size"); // this is data encription ratio

// decrept

console.log("decrypted:  " de(secondStep))

function en(c){var x='charCodeAt',b,e={},f=c.split(""),d=[],a=f[0],g=256;for(b=1;b<f.length;b  )c=f[b],null!=e[a c]?a =c:(d.push(1<a.length?e[a]:a[x](0)),e[a c]=g,g  ,a=c);d.push(1<a.length?e[a]:a[x](0));for(b=0;b<d.length;b  )d[b]=String.fromCharCode(d[b]);return d.join("")}

function de(b){var a,e={},d=b.split(""),c=f=d[0],g=[c],h=o=256;for(b=1;b<d.length;b  )a=d[b].charCodeAt(0),a=h>a?d[b]:e[a]?e[a]:f c,g.push(a),c=a.charAt(0),e[o]=f c,o  ,f=a;return g.join("")}

  • Related