slow-json-stringify

by lucagez

The slowest stringifier in the known universe. Just kidding, it's the fastest (:

220 Stars 8 Forks Last release: Not found MIT License 91 Commits 0 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

slow-json-stringify logo
travis npm MIT gzip size

SJS

The slowest stringifier in the known universe. Just kidding, it's the fastest (:

TOC

TL;DR

SJS
shows a significant increase in performance over both native
JSON.stringify
and
fast-json-stringify
. For some use cases (dealing with long text), it performs 21000% faster than both native and
fast-json-stringify
.

NOTE: Support for undefined properties has been added from 1.0.1.

SJS
is now production ready.

Checkout benchmarks.

Installation

SJS
is fully compatible with both Node.js and the browser πŸŽ‰πŸŽ‰

Node:

bash
npm install slow-json-stringify

On the browser:

html

How it works

Why

SJS
is the fastest stringifier? The traditional approach consists in serializing every property taken singularly.
SJS
uses a different approach to serialization.

Preparation: - A schema is provided - The schema is stringified - A templated string is built with the provided schema.

Serialization: - Object values are inserted in the already built template.

It is faster simply because it performs a lot less work.

Caveats

SJS
require some setup work if compared to native
JSON.stringify
. But, if you are dealing with json with a fixed structure
SJS
will save you a ton of time. Especially when the payload grows. And incredibly when serializing json with long text inside (think of a blog article or a product description. Moreover,
SJS
makes possible the serialization of types that are not natively supported by
JSON.stringify
thanks to custom serializers.

note:

SJS
won't perform any escaping as you usually won't need it in small payloads. If you are working with big text, it could be of very little effort to store in your db an already escaped text.

However,

SJS
provides a little utility for your escaping needs.
escape
uses a default regex if no additional regex is provided.

default regex string:

javascript
/\n|\r|\t|\"|\\/gm

You can use

escape
like the following:
const { escape } = require('slow-json-stringify');

// If you don't pass any additional regex, a default one will be used. const escaper = escape();

escaper('This is "funny"'); // This is "funny"

// You can pass any regex you want for your escaping strategy. const customEscaper = escape(/"/gm);

customEscaper('This is "funny"'); // This is "funny"

Benchmarks

We all know that there are three kinds of lies..

Lies, damned lies.. and benchmarks.

Remember to test if

SJS
could be a real improvement for your use case. Because there are times when the performance advantages with the added drawbacks could not be worth it.

Running the benchmarks

Every benchmark is replicable on your own machine. To run your tests: - Clone this repo. - Install dependencies. -

cd benchmark
. - Grant executable rights to
run.sh
script
chmod +x ./run.sh
. - Save benchmark results to file
./run.sh >> benchmark.md

Test machine

The benchmarks were performed on a Dell Xps 15 9550. - cpu: intel i7 6700HQ - ram: 16gb - os: Ubuntu 18.04

Some numbers

Checkout benchmarks here

Usage

Supported types

The schema creation happens thanks to the

attr
helper exported from the main bundle.
const { attr } = require('sjs');
attr(type, serializer?)

The

attr
helper natively supports the following types: -
string
-
number
-
boolean
-
null
-
array
, dynamic array with simple structure, in this scenario native
JSON.stringify
will be used. As there are no real performance advantages.

The serialization of any other type is possible thanks to custom serializers.

Defining a schema

For a correct stringification of your json payload, a correct schema is mandatory. Defining a schema is pretty handy and not verbose at all.

const { sjs } = require('slow-json-stringify');

// schema definition const stringify = sjs({ a: attr('string'), b: attr('number'), c: attr('boolean'), });

// then you can stringify anything with that structure. stringify({ a: 'world', b: 42, c: true, });

// {"a":"world","b":42,"c":true}

Defining schema with simple array

When stringifying simple array

JSON.stringify
will be internally used.
const { sjs } = require('slow-json-stringify');

// schema definition const stringify = sjs({ a: attr('array'), });

// then you can stringify anything with that structure. stringify({ a: [1, 2, 3, true, 'world'], });

// {"a":[1,2,3,true,"world"]}

Defining schema with complex array

The

attr
helper accepts an additional
sjs
schema for
array
properties.
const { sjs } = require('slow-json-stringify');

// schema definition const stringify = sjs({ a: attr('array', sjs({ b: array('string'), c: array('number'), })) });

// then you can stringify anything with that structure. stringify({ a: [{ b: 'ciao1', c: 1, }, { b: 'ciao2', c: 2, }, { b: 'ciao3', c: 3, }, { b: 'ciao4', c: 4, }], });

// {"a":[{"b":"ciao1","c":1},{"b":"ciao2","c":2},{"b":"ciao3","c":3},{"b":"ciao4","c":4}]}

Defining schema with nested objects

Defining schemas with nested objects is pretty straightforward.

const { sjs } = require('slow-json-stringify');

// schema definition const stringify = sjs({ a: { b: { c: attr('string'), }, }, d: { e: attr('number'), }, });

stringify({ a: { b: { c: 'hello', }, }, d: { e: 42, }, });

// {"a":{"b":{"c":"hello"}},"d":{"e":42}}

Serializers

The

attr
helper accepts a serializer function. The serializer function gets invoked with the real value that should be stringified.
serializer(rawValue)

Property serializers are useful to perform custom serialization on any provide type not natively supported even by

JSON.stringify
(Dates, regular expressions). They can be used also to skip property serializarion when returning
undefined
.
const { sjs } = require('slow-json-stringify');

// schema definition const stringify = sjs({ a: attr('number', (value) => { if (value > 10) { return value; }

return undefined;

}) });

stringify({ a: 20 }); // {"a":20}

stringify({ a: 5 }); // {}

use case: Serialization of any type.

// DATES
const stringify = sjs({
  date: attr('string', (value) => value.toLocaleString()),
});

// REGEXP const stringify = sjs({ regexp: attr('string', (value) => value.toString()), });

use case: Customize payloads based on access rights.

const stringify = sjs({
  publicProp: attr('string'),
  restrictedProp: attr('string', (value) => isAdmin ? value : undefined),
});

use case: Value formatting

const stringify = sjs({
  prop: attr('string', (value) => value.toUpperCase()),
});

API

sjs

| param | type | required | default | spec | |--------|---------|------------------------------------|-----------|-----------------------------------------------------| | schema | object | yes | undefined | Schema that defines the stringification behavior. |

attr

| param | type | required | default | spec | |------------|----------|------------------------------------|-----------|--------------------------------------------------------| | type | string | yes | undefined | Type of the property. | | serializer | function | no | identity | Function used for serializing / validating properties. |

escape

| param | type | required | default | spec | |-------|--------------------|------------------------------------|---------------------------|-----------------------------------------------------| | regex | Regular Expression | no | default regex | regex used to escape text |

License

MIT.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.