flightcontrolhq / superjson

Safely serialize JavaScript expressions to a superset of JSON, which includes Dates, BigInts, and more.
https://www.flightcontrol.dev?ref=superjson
MIT License
4.12k stars 90 forks source link

Ideas on reducing `meta`'s footprint #11

Open Skn0tt opened 4 years ago

Skn0tt commented 4 years ago

Beware! This issue is not meant to say "We need this now" or even "We need this" at all. Keeping SuperJSON human-readable is a big advantage that should not be underestimated. This issue just aims to keep ideas on how to compress it in case there's a need for that in the future, which most likely won't occur.


Idea 1: Nesting Meta

At the moment, our meta looks like the following:

{
  "a.deep.nested.path.containing.multiple.keys": "map",
  "a.deep.nested.path.containing.multiple.keys.a": "number",
  "a.deep.nested.path.containing.multiple.keys.b": "number",
}

(177 chars)

This is wasteful. It would be much better to have this nested like the following:

{
  "a": { "deep": { "nested": { "path": { "containing": { "multiple": { "keys": [
     "map",
     { "a": "number", "b": "number" }
  ] } } } } } }
}

(134 chars)

Or even better:

{
  "a.deep.nested.path.containing.multiple.keys": [
    "map",
    {
      "a": "number",
      "b": "number",
    }
  ]
}

(115 chars)

Idea 2: Hashing keys

Instead of storing the full key, we could compute a hash of it and store the prefix that uniquely identifies it amongst the other keys.

Example: Key: a.deep.nested.path Hash: 1108f7... (this is MD5, but any hash function works) Hashes of the other keys: 90fa1..., 994da..., 110d3....

These hashes can then be shortened to the following, making them uniquely identifiable: 1, 9, 99 and 11. They can then be matched to their original keys during revival by hashing the keys in value.

Beware: For undefined values, there are keys in meta that aren't present in value. They need to be accounted for.

Idea 3: Shortening meta descriptors

At the moment, the descriptors in meta are rather long. We could potentially enumerate them using integers or characters instead of lengthy strings.

Idea 4: Use non-JSON-encoding

meta does not necessarily need to be parsable for users outside of SuperJSON. To save a lot of characters, we could use some binary encoding or something like Avro or ProtoBuf.

Mansi1 commented 1 month ago

One question if you already changing the structure maybe think about to have it all in one place instead of a separated meta. like an extension TS superset of JS like

{date: new Date()};
{date: {"$t": "jsdom.Date", value: "2024-09-10T13:25:10.621Z"}