lucagez / slow-json-stringify

The slowest stringifier in the known universe. Just kidding, it's the fastest (:
https://github.com/lucagez/slow-json-stringify
MIT License
468 stars 17 forks source link

Does this library support serializing objects with circular references? #24

Closed mrjjwright closed 3 years ago

mrjjwright commented 3 years ago

thank you!

lucagez commented 3 years ago

@mrjjwright circular references are handled quite gracefully actually. You just need to define the target type you want them to be serialized with.

const stringify = sjs({
  a: attr('boolean'),
  b: attr('number'),
  circular: attr('string'), // <= Target type
});

const obj = {
  a: true,
  b: 42,
}

obj.circular = obj;

const str = stringify(obj);
// => {"a":true,"b":42,"circular":"[object Object]"}

But you can also customize how the serialization is handled in the first place.

Remove circular property

const stringify = sjs({
  a: attr('boolean'),
  b: attr('number'),
  circular: attr('string', () => undefined),
});

const str = stringify(obj);
// => {"a":true,"b":42}

Add a placeholder for the property

const stringify = sjs({
  a: attr('boolean'),
  b: attr('number'),
  circular: attr('string', () => '<circular>'),
});

const str = stringify(obj);
// => {"a":true,"b":42,"circular":"<circular>"}
mrjjwright commented 3 years ago

Freaking awesome, thanks!!

mrjjwright commented 3 years ago

Can I serialize recursive schemas/structures?

lucagez commented 3 years ago

What is the difference between a circular structure and a recursive structure? Could you provide an example?

mrjjwright commented 3 years ago

I just need to serialize a tree like structure that I don't know the exact shape of but I do know that it repeats and nests smaller structures that have a known schema.

lucagez commented 3 years ago

@mrjjwright In that case the solution would be a bit more involved. A possible approach I can see is:

const serializer1 = sjs({ ... })
const serializer2 = sjs({ ... })

const mainSchema = sjs({
   unknownNested: attr('null', (value) => {
      if (type of value === 'type1') {
        return serializer1(value)
      }
      return serializer2(value)
   })
})

Note that this approach can keep nesting indefinitely. As any schema can keep referring to other schemas. Also, I used the null value in the attr helper as this approach was not thought as out of the box.

I opened an issue for discussing optimizations for serializing Objects with unknow shapes here https://github.com/lucagez/slow-json-stringify/issues/28. Feel free to leave suggestions there if you have ideas!

mrjjwright commented 3 years ago

This makes sense to me and should work great, thanks!