Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork208
2x faster than JSON.stringify()
License
fastify/fast-json-stringify
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
fast-json-stringify is significantly faster thanJSON.stringify() for small payloads.Its performance advantage shrinks as your payload grows.
fast-json-stringify requires aJSON Schema Draft 7 input to generate a faststringify function.
- Machine:
EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD. - Node.js
v22.14.0
FJS creation x 9,696 ops/sec ±0.77% (94 runs sampled)CJS creation x 197,267 ops/sec ±0.22% (95 runs sampled)AJV Serialize creation x 48,302,927 ops/sec ±2.09% (90 runs sampled)json-accelerator creation x 668,430 ops/sec ±0.43% (95 runs sampled)JSON.stringify array x 7,924 ops/sec ±0.11% (98 runs sampled)fast-json-stringify array default x 7,183 ops/sec ±0.09% (97 runs sampled)json-accelerator array x 5,762 ops/sec ±0.27% (99 runs sampled)fast-json-stringify array json-stringify x 7,171 ops/sec ±0.17% (97 runs sampled)compile-json-stringify array x 6,889 ops/sec ±0.41% (96 runs sampled)AJV Serialize array x 6,945 ops/sec ±0.17% (98 runs sampled)JSON.stringify large array x 331 ops/sec ±0.17% (93 runs sampled)fast-json-stringify large array default x 208 ops/sec ±0.21% (91 runs sampled)fast-json-stringify large array json-stringify x 330 ops/sec ±0.17% (93 runs sampled)compile-json-stringify large array x 318 ops/sec ±0.11% (90 runs sampled)AJV Serialize large array x 114 ops/sec ±0.27% (74 runs sampled)JSON.stringify long string x 13,452 ops/sec ±0.15% (99 runs sampled)fast-json-stringify long string x 13,454 ops/sec ±0.10% (99 runs sampled)json-accelerator long string x 13,439 ops/sec ±0.09% (98 runs sampled)compile-json-stringify long string x 13,380 ops/sec ±0.12% (100 runs sampled)AJV Serialize long string x 21,932 ops/sec ±0.06% (99 runs sampled)JSON.stringify short string x 12,114,052 ops/sec ±0.59% (97 runs sampled)fast-json-stringify short string x 29,408,175 ops/sec ±1.12% (91 runs sampled)json-accelerator short string x 29,431,694 ops/sec ±1.05% (93 runs sampled)compile-json-stringify short string x 24,740,338 ops/sec ±1.02% (91 runs sampled)AJV Serialize short string x 17,841,869 ops/sec ±0.90% (91 runs sampled)JSON.stringify obj x 4,577,494 ops/sec ±0.25% (94 runs sampled)fast-json-stringify obj x 7,291,157 ops/sec ±0.40% (97 runs sampled)json-accelerator obj x 6,473,194 ops/sec ±0.31% (99 runs sampled)compile-json-stringify obj x 14,724,935 ops/sec ±0.50% (96 runs sampled)AJV Serialize obj x 8,782,944 ops/sec ±0.45% (93 runs sampled)JSON stringify date x 803,522 ops/sec ±0.47% (98 runs sampled)fast-json-stringify date format x 1,117,776 ops/sec ±0.69% (95 runs sampled)json-accelerate date format x 1,122,419 ops/sec ±0.20% (97 runs sampled)compile-json-stringify date format x 803,214 ops/sec ±0.23% (97 runs sampled)ExampleOptionsAPIfastJsonStringifySpecific use casesRequiredMissing fieldsPattern PropertiesAdditional PropertiesAnyOfandOneOfReuse - $refLong integersIntegersNullableLarge ArraysSecurity NoticeDebug ModeStandalone ModeAcknowledgmentsLicense
Try it out on RunKit:https://runkit.com/npm/fast-json-stringify
constfastJson=require('fast-json-stringify')conststringify=fastJson({title:'Example Schema',type:'object',properties:{firstName:{type:'string'},lastName:{type:'string'},age:{description:'Age in years',type:'integer'},reg:{type:'string'}}})console.log(stringify({firstName:'Matteo',lastName:'Collina',age:32,reg:/"([^"]|\\")*"/}))
Optionally, you may provide tofast-json-stringify an option object as the second parameter:
constfastJson=require('fast-json-stringify')conststringify=fastJson(mySchema,{schema:{ ...},ajv:{ ...},rounding:'ceil'})
schema: external schemas references by $ref property.More detailsajv:ajv v8 instance's settings for those properties that requireajv.More detailsrounding: setup how theintegertypes will be rounded when not integers.More detailslargeArrayMechanism: set the mechanism that should be used to handle large(by default20000or more items) arrays.More details
Build astringify() function based onjsonschema draft 7 spec.
Supported types:
'string''integer''number''array''object''boolean''null'
And nested ones, too.
| Instance | Serialized as |
|---|---|
Date | string viatoISOString() |
RegExp | string |
BigInt | integer viatoString |
JSON Schema built-in formats for dates are supported and will be serialized as:
| Format | Serialized format example |
|---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
Note: In the case of a string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
Example with a Date object:
conststringify=fastJson({title:'Example Schema with string date-time field',type:'string',format:'date-time'})constdate=newDate()console.log(stringify(date))// '"YYYY-MM-DDTHH:mm:ss.sssZ"'
You can set specific fields of an object as required in your schema by adding the field name inside therequired array in your schema.Example:
constschema={title:'Example Schema with required field',type:'object',properties:{nickname:{type:'string'},mail:{type:'string'}},required:['mail']}
If the object to stringify is missing the required field(s),fast-json-stringify will throw an error.
If a fieldis present in the schema (and is not required) but itis not present in the object to stringify,fast-json-stringify will not write it in the final string.Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{nickname:{type:'string'},mail:{type:'string'}}})constobj={mail:'mail@example.com'}console.log(stringify(obj))// '{"mail":"mail@example.com"}'
fast-json-stringify supportsdefault jsonschema key in order to serialize a valueif it isundefined or not present.
Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{nickname:{type:'string',default:'the default string'}}})console.log(stringify({}))// '{"nickname":"the default string"}'console.log(stringify({nickname:'my-nickname'}))// '{"nickname":"my-nickname"}'
fast-json-stringify supports pattern properties as defined by JSON schema.patternProperties must be an object, where the key is a valid regex and the value is an object, declared in this way:{ type: 'type' }.patternProperties will work only for the properties that are not explicitly listed in the properties object.Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{nickname:{type:'string'}},patternProperties:{'num':{type:'number'},'.*foo$':{type:'string'}}})constobj={nickname:'nick',matchfoo:42,otherfoo:'str',matchnum:3}console.log(stringify(obj))// '{"matchfoo":"42","otherfoo":"str","matchnum":3,"nickname":"nick"}'
fast-json-stringify supports additional properties as defined by JSON schema.additionalProperties must be an object or a boolean, declared in this way:{ type: 'type' }.additionalProperties will work only for the properties that are not explicitly listed in theproperties andpatternProperties objects.
IfadditionalProperties is not present or is set tofalse, every property that is not explicitly listed in theproperties andpatternProperties objects will be ignored, as described inMissing fields.Missing fields are ignored to avoid having to rewrite objects before serializing. However, other schema rules would throw in similar situations.IfadditionalProperties is set totrue, it will be used byJSON.stringify to stringify the additional properties. If you want to achieve maximum performance, we strongly encourage you to use a fixed schema where possible.The additional properties will always be serialized at the end of the object.Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{nickname:{type:'string'}},patternProperties:{'num':{type:'number'},'.*foo$':{type:'string'}},additionalProperties:{type:'string'}})constobj={nickname:'nick',matchfoo:42,otherfoo:'str',matchnum:3,nomatchstr:'valar morghulis',nomatchint:313}console.log(stringify(obj))// '{"nickname":"nick","matchfoo":"42","otherfoo":"str","matchnum":3,"nomatchstr":"valar morghulis",nomatchint:"313"}'
fast-json-stringify supports theanyOf andoneOf keywords as defined by JSON schema. Both must be an array of valid JSON schemas. The different schemas will be tested in the specified order. The more schemasstringify has to try before finding a match, the slower it will be.
anyOf andoneOf useajv as a JSON schema validator to find the schema that matches the data. This has an impact on performance—only use it as a last resort.
Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{'undecidedType':{'anyOf':[{type:'string'},{type:'boolean'}]}}})
When specifying object JSON schemas foranyOf, addrequired validation keyword to match only the objects with the properties you want.
Example:
conststringify=fastJson({title:'Example Schema',type:'array',items:{anyOf:[{type:'object',properties:{savedId:{type:'string'}},// without "required" validation any object will matchrequired:['savedId']},{type:'object',properties:{error:{type:'string'}},required:['error']}]}})
fast-json-stringify supportsif/then/else jsonschema feature. Seeajv documentation.
Example:
conststringify=fastJson({'type':'object','properties':{},'if':{'properties':{'kind':{'type':'string','enum':['foobar']}}},'then':{'properties':{'kind':{'type':'string','enum':['foobar']},'foo':{'type':'string'},'bar':{'type':'number'}}},'else':{'properties':{'kind':{'type':'string','enum':['greeting']},'hi':{'type':'string'},'hello':{'type':'number'}}}})console.log(stringify({kind:'greeting',foo:'FOO',bar:42,hi:'HI',hello:45}))// {"kind":"greeting","hi":"HI","hello":45}console.log(stringify({kind:'foobar',foo:'FOO',bar:42,hi:'HI',hello:45}))// {"kind":"foobar","foo":"FOO","bar":42}
NB Do not declare the properties twice or you will print them twice!
If you want to reuse a definition of a value, you can use the property$ref.The value of$ref must be a string inJSON Pointer format.Example:
constschema={title:'Example Schema',definitions:{num:{type:'object',properties:{int:{type:'integer'}}},str:{type:'string'}},type:'object',properties:{nickname:{$ref:'#/definitions/str'}},patternProperties:{'num':{$ref:'#/definitions/num'}},additionalProperties:{$ref:'#/definitions/def'}}conststringify=fastJson(schema)
If you need to use an external definition, you can pass it as an option tofast-json-stringify.Example:
constschema={title:'Example Schema',type:'object',properties:{nickname:{$ref:'strings#/definitions/str'}},patternProperties:{'num':{$ref:'numbers#/definitions/num'}},additionalProperties:{$ref:'strings#/definitions/def'}}constexternalSchema={numbers:{definitions:{num:{type:'object',properties:{int:{type:'integer'}}}}},strings:require('./string-def.json')}conststringify=fastJson(schema,{schema:externalSchema})
External definitions can also reference each other.Example:
constschema={title:'Example Schema',type:'object',properties:{foo:{$ref:'strings#/definitions/foo'}}}constexternalSchema={strings:{definitions:{foo:{$ref:'things#/definitions/foo'}}},things:{definitions:{foo:{type:'string'}}}}conststringify=fastJson(schema,{schema:externalSchema})
By default, the library will handle automaticallyBigInt.
Thetype: integer property will be truncated if a floating point is provided.You can customize this behavior with therounding option that will acceptround,ceil,floor, ortrunc. Default istrunc:
conststringify=fastJson(schema,{rounding:'ceil'})
According to theOpen API 3.0 specification, a value that can be null must be declarednullable.
conststringify=fastJson({'title':'Nullable schema','type':'object','nullable':true,'properties':{'product':{'nullable':true,'type':'object','properties':{'name':{'type':'string'}}}}})console.log(stringify({product:{name:"hello"}}))// "{"product":{"name":"hello"}}"console.log(stringify({product:null}))// "{"product":null}"console.log(stringify(null))// null
Otherwise, instead of raising an error, null values will be coerced as follows:
integer->0number->0string->""boolean->falseobject->{}array->[]
Large arrays are, for the scope of this document, defined as arrays containing,by default,20000 elements or more. That value can be adjusted via the optionparameterlargeArraySize.
At some point the overhead caused by the default mechanism used byfast-json-stringify to handle arrays starts increasing exponentially, leadingto slow overall executions.
In order to improve that the user can set thelargeArrayMechanism andlargeArraySize options.
largeArrayMechanism's default value isdefault. Valid values for it are:
default- This option is a compromise between performance and feature set bystill providing the expected functionality out of this lib but giving up somepossible performance gain. With this option set,large arrays would bestringified by joining their stringified elements usingArray.joininstead ofstring concatenation for better performancejson-stringify- This option will remove support for schema validationwithinlarge arrays completely. By doing so the overhead previouslymentioned is nulled, greatly improving execution time. Mind there's no changein behavior for arrays not consideredlarge
largeArraySize's default value is20000. Valid values for it areinteger-like values, such as:
200002e4'20000''2e4'-note this will be converted to2, not200001.5-note this will be converted to1
By default, the library escapes all strings. With the 'unsafe' format, the string isn't escaped. This has a potentially dangerous security issue. You can use it only if you are sure that your data doesn't need escaping. The advantage is a significant performance improvement.
Example:
conststringify=fastJson({title:'Example Schema',type:'object',properties:{'code':{type:'string',format'unsafe'}}})
For reference, here are some benchmarks for comparison over the threemechanisms. Benchmarks were conducted on an old machine.
- Machine:
ST1000LM024 HN-M 1TB HDD, Intel Core i7-3610QM @ 2.3GHz, 12GB RAM, 4C/8T. - Node.js
v16.13.1
JSON.stringify large array x 157 ops/sec ±0.73% (86 runs sampled)fast-json-stringify large array default x 48.72 ops/sec ±4.92% (48 runs sampled)fast-json-stringify large array json-stringify x 157 ops/sec ±0.76% (86 runs sampled)compile-json-stringify large array x 175 ops/sec ±4.47% (79 runs sampled)AJV Serialize large array x 58.76 ops/sec ±4.59% (60 runs sampled)Treat the schema definition as application code, itis not safe to use user-provided schemas.
To achieve low cost and high performance redactionfast-json-stringifycreates and compiles a function (using theFunction constructor) on initialization.While theschema is currently validated for any developer errors,there is no guarantee that supplying user-generated schema could notexpose your application to remote attacks.
Users are responsible for sending trusted data.fast-json-stringify guarantees that you will geta valid output only if your input matches the schema or can be coerced to the schema. If your inputdoesn't match the schema, you will get undefined behavior.
The debug mode can be activated during your development to understand what is going on when things do notwork as you expect.
constdebugCompiled=fastJson({title:'default string',type:'object',properties:{firstName:{type:'string'}}},{mode:'debug'})console.log(debugCompiled)// it is a object contain code, ajv instanceconstrawString=debugCompiled.code// it is the generated codeconsole.log(rawString)conststringify=fastJson.restore(debugCompiled)// use the generated string to get back the `stringify` functionconsole.log(stringify({firstName:'Foo',surname:'bar'}))// '{"firstName":"Foo"}'
The standalone mode is used to compile the code that can be directly run bynodeitself. You need to havefast-json-stringify installed for the standalone code to work.
constfs=require('fs')constcode=fastJson({title:'default string',type:'object',properties:{firstName:{type:'string'}}},{mode:'standalone'})fs.writeFileSync('stringify.js',code)conststringify=require('stringify.js')console.log(stringify({firstName:'Foo',surname:'bar'}))// '{"firstName":"Foo"}'
This project was kindly sponsored bynearForm.
Licensed underMIT.
About
2x faster than JSON.stringify()
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.