fast-json-stringify est nettement plus rapide que JSON.stringify()
pour les petites charges utiles. Son avantage en termes de performances diminue à mesure que votre charge utile augmente. Il se marie bien avec flatstr , qui déclenche une optimisation V8 qui améliore les performances lors de la conversion éventuelle de la chaîne en Buffer
.
fast-json-stringify nécessite une entrée JSON Schema Draft 7 pour générer une fonction fast stringify
.
EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD
.v18.12.1
FJS creation x 4,129 ops/sec ±0.82% (92 runs sampled)
CJS creation x 184,196 ops/sec ±0.12% (97 runs sampled)
AJV Serialize creation x 61,130,591 ops/sec ±0.40% (92 runs sampled)
JSON.stringify array x 5,057 ops/sec ±0.10% (100 runs sampled)
fast-json-stringify array default x 6,243 ops/sec ±0.14% (98 runs sampled)
fast-json-stringify array json-stringify x 6,261 ops/sec ±0.30% (99 runs sampled)
compile-json-stringify array x 6,842 ops/sec ±0.18% (96 runs sampled)
AJV Serialize array x 6,964 ops/sec ±0.11% (95 runs sampled)
JSON.stringify large array x 248 ops/sec ±0.07% (90 runs sampled)
fast-json-stringify large array default x 99.96 ops/sec ±0.22% (74 runs sampled)
fast-json-stringify large array json-stringify x 248 ops/sec ±0.07% (90 runs sampled)
compile-json-stringify large array x 317 ops/sec ±0.09% (89 runs sampled)
AJV Serialize large array x 111 ops/sec ±0.07% (33 runs sampled)
JSON.stringify long string x 16,002 ops/sec ±0.09% (98 runs sampled)
fast-json-stringify long string x 15,979 ops/sec ±0.09% (96 runs sampled)
compile-json-stringify long string x 15,952 ops/sec ±0.31% (97 runs sampled)
AJV Serialize long string x 21,416 ops/sec ±0.08% (98 runs sampled)
JSON.stringify short string x 12,944,272 ops/sec ±0.09% (96 runs sampled)
fast-json-stringify short string x 30,585,790 ops/sec ±0.27% (97 runs sampled)
compile-json-stringify short string x 30,656,406 ops/sec ±0.12% (96 runs sampled)
AJV Serialize short string x 30,406,785 ops/sec ±0.37% (96 runs sampled)
JSON.stringify obj x 3,153,043 ops/sec ±0.33% (99 runs sampled)
fast-json-stringify obj x 6,866,434 ops/sec ±0.11% (100 runs sampled)
compile-json-stringify obj x 15,886,723 ops/sec ±0.15% (98 runs sampled)
AJV Serialize obj x 8,969,043 ops/sec ±0.36% (97 runs sampled)
JSON stringify date x 1,126,547 ops/sec ±0.09% (97 runs sampled)
fast-json-stringify date format x 1,836,188 ops/sec ±0.12% (99 runs sampled)
compile-json-stringify date format x 1,125,735 ops/sec ±0.19% (98 runs sampled)
Example
Options
API
fastJsonStringify
Specific use cases
Required
Missing fields
Pattern Properties
Additional Properties
AnyOf
et OneOf
Reuse - $ref
Long integers
Integers
Nullable
Large Arrays
Security Notice
Debug Mode
Standalone Mode
Acknowledgements
License
Essayez-le sur RunKit : https://runkit.com/npm/fast-json-stringify
const fastJson = require ( 'fast-json-stringify' )
const stringify = 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 : / "([^"]|\")*" /
} ) )
En option, vous pouvez proposer de fast-json-stringify
un objet option comme deuxième paramètre :
const fastJson = require ( 'fast-json-stringify' )
const stringify = fastJson ( mySchema , {
schema : { ... } ,
ajv : { ... } ,
rounding : 'ceil'
} )
schema
: références de schémas externes par propriété $ref. Plus de détailsajv
: paramètres de l'instance ajv v8 pour les propriétés qui nécessitent ajv
. Plus de détailsrounding
: configurez la manière dont les types integer
seront arrondis lorsqu'ils ne sont pas des entiers. Plus de détailslargeArrayMechanism
: définit le mécanisme qui doit être utilisé pour gérer de grands tableaux (par défaut 20000
éléments ou plus). Plus de détails Créez une fonction stringify()
basée sur la spécification jsonschema draft 7.
Types pris en charge :
'string'
'integer'
'number'
'array'
'object'
'boolean'
'null'
Et ceux imbriqués aussi.
Exemple | Sérialisé comme |
---|---|
Date | string via toISOString() |
RegExp | string |
BigInt | integer via toString |
Les formats intégrés de schéma JSON pour les dates sont pris en charge et seront sérialisés comme :
Format | Exemple de format sérialisé |
---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
Remarque : Dans le cas d'une Date au format chaîne et non d'un Objet Date, il n'y aura aucune manipulation sur celui-ci. Il doit être correctement formaté.
Exemple avec un objet Date :
const stringify = fastJson ( {
title : 'Example Schema with string date-time field' ,
type : 'string' ,
format : 'date-time'
} )
const date = new Date ( )
console . log ( stringify ( date ) ) // '"YYYY-MM-DDTHH:mm:ss.sssZ"'
Vous pouvez définir des champs spécifiques d'un objet comme requis dans votre schéma en ajoutant le nom du champ dans le tableau required
dans votre schéma. Exemple:
const schema = {
title : 'Example Schema with required field' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
} ,
mail : {
type : 'string'
}
} ,
required : [ 'mail' ]
}
Si l'objet à stringify ne contient pas le(s) champ(s) requis, fast-json-stringify
générera une erreur.
Si un champ est présent dans le schéma (et n'est pas obligatoire) mais qu'il n'est pas présent dans l'objet à stringify, fast-json-stringify
ne l'écrira pas dans la chaîne finale. Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
} ,
mail : {
type : 'string'
}
}
} )
const obj = {
mail : '[email protected]'
}
console . log ( stringify ( obj ) ) // '{"mail":"[email protected]"}'
fast-json-stringify
prend en charge la clé jsonschema default
afin de sérialiser une valeur si elle undefined
ou n'est pas présente.
Exemple:
const stringify = 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
prend en charge les propriétés de modèle telles que définies par le schéma JSON. patternProperties doit être un objet, où la clé est une expression régulière valide et la valeur est un objet, déclaré de cette manière : { type: 'type' }
. patternProperties ne fonctionnera que pour les propriétés qui ne sont pas explicitement répertoriées dans l'objet propriétés. Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
}
} ,
patternProperties : {
'num' : {
type : 'number'
} ,
'.*foo$' : {
type : 'string'
}
}
} )
const obj = {
nickname : 'nick' ,
matchfoo : 42 ,
otherfoo : 'str' ,
matchnum : 3
}
console . log ( stringify ( obj ) ) // '{"matchfoo":"42","otherfoo":"str","matchnum":3,"nickname":"nick"}'
fast-json-stringify
prend en charge des propriétés supplémentaires telles que définies par le schéma JSON. additionnelProperties doit être un objet ou un booléen, déclaré de cette manière : { type: 'type' }
. additionnelProperties ne fonctionnera que pour les propriétés qui ne sont pas explicitement répertoriées dans les objets propriétés et patternProperties .
Si additionnelProperties n'est pas présent ou est défini sur false
, chaque propriété qui n'est pas explicitement répertoriée dans les objets propriétés et patternProperties sera ignorée, comme décrit dans Champs manquants. Les champs manquants sont ignorés pour éviter d'avoir à réécrire les objets avant la sérialisation. Cependant, d’autres règles de schéma pourraient se produire dans des situations similaires. Si additionnelProperties est défini sur true
, il sera utilisé par JSON.stringify
pour stringifier les propriétés supplémentaires. Si vous souhaitez obtenir des performances maximales, nous vous encourageons fortement à utiliser un schéma fixe lorsque cela est possible. Les propriétés supplémentaires seront toujours sérialisées à la fin de l'objet. Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
}
} ,
patternProperties : {
'num' : {
type : 'number'
} ,
'.*foo$' : {
type : 'string'
}
} ,
additionalProperties : {
type : 'string'
}
} )
const obj = {
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
prend en charge les mots-clés anyOf et oneOf tels que définis par le schéma JSON. Les deux doivent être un tableau de schémas JSON valides. Les différents schémas seront testés dans l'ordre spécifié. Plus les schémas stringify
doivent essayer avant de trouver une correspondance, plus cela sera lent.
anyOf et oneOf utilisent ajv comme validateur de schéma JSON pour trouver le schéma qui correspond aux données. Cela a un impact sur les performances : utilisez-le uniquement en dernier recours.
Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'undecidedType' : {
'anyOf' : [ {
type : 'string'
} , {
type : 'boolean'
} ]
}
}
} )
Lorsque vous spécifiez des schémas JSON d'objet pour anyOf , ajoutez le mot-clé de validation requis pour faire correspondre uniquement les objets avec les propriétés souhaitées.
Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'array' ,
items : {
anyOf : [
{
type : 'object' ,
properties : {
savedId : { type : 'string' }
} ,
// without "required" validation any object will match
required : [ 'savedId' ]
} ,
{
type : 'object' ,
properties : {
error : { type : 'string' }
} ,
required : [ 'error' ]
}
]
}
} )
fast-json-stringify
prend en charge la fonctionnalité if/then/else
jsonschema. Voir la documentation ajv.
Exemple:
const stringify = 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 Ne déclarez pas les propriétés deux fois sous peine de les imprimer deux fois !
Si vous souhaitez réutiliser une définition d'une valeur, vous pouvez utiliser la propriété $ref
. La valeur de $ref
doit être une chaîne au format JSON Pointer. Exemple:
const schema = {
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'
}
}
const stringify = fastJson ( schema )
Si vous devez utiliser une définition externe, vous pouvez la transmettre en option à fast-json-stringify
. Exemple:
const schema = {
title : 'Example Schema' ,
type : 'object' ,
properties : {
nickname : {
$ref : 'strings#/definitions/str'
}
} ,
patternProperties : {
'num' : {
$ref : 'numbers#/definitions/num'
}
} ,
additionalProperties : {
$ref : 'strings#/definitions/def'
}
}
const externalSchema = {
numbers : {
definitions : {
num : {
type : 'object' ,
properties : {
int : {
type : 'integer'
}
}
}
}
} ,
strings : require ( './string-def.json' )
}
const stringify = fastJson ( schema , { schema : externalSchema } )
Les définitions externes peuvent également se référencer mutuellement. Exemple:
const schema = {
title : 'Example Schema' ,
type : 'object' ,
properties : {
foo : {
$ref : 'strings#/definitions/foo'
}
}
}
const externalSchema = {
strings : {
definitions : {
foo : {
$ref : 'things#/definitions/foo'
}
}
} ,
things : {
definitions : {
foo : {
type : 'string'
}
}
}
}
const stringify = fastJson ( schema , { schema : externalSchema } )
Par défaut, la bibliothèque gérera automatiquement BigInt.
La propriété type: integer
sera tronquée si une virgule flottante est fournie. Vous pouvez personnaliser ce comportement avec l'option rounding
qui acceptera round
, ceil
, floor
ou trunc
. La valeur par défaut est trunc
:
const stringify = fastJson ( schema , { rounding : 'ceil' } )
Selon la spécification Open API 3.0, une valeur qui peut être nulle doit être déclarée nullable
.
const stringify = 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
Sinon, au lieu de générer une erreur, les valeurs nulles seront forcées comme suit :
integer
-> 0
number
-> 0
string
-> ""
boolean
-> false
object
-> {}
array
-> []
Les grands tableaux sont, dans le cadre de ce document, définis comme des tableaux contenant, par défaut, 20000
éléments ou plus. Cette valeur peut être ajustée via le paramètre d'option largeArraySize
.
À un moment donné, la surcharge provoquée par le mécanisme par défaut utilisé par fast-json-stringify
pour gérer les tableaux commence à augmenter de façon exponentielle, entraînant un ralentissement des exécutions globales.
Afin d'améliorer cela, l'utilisateur peut définir les options largeArrayMechanism
et largeArraySize
.
La valeur par défaut de largeArrayMechanism
est default
. Les valeurs valides pour cela sont :
default
- Cette option est un compromis entre les performances et l'ensemble des fonctionnalités en fournissant toujours les fonctionnalités attendues de cette bibliothèque mais en abandonnant certains gains de performances possibles. Avec cette option définie, les grands tableaux seraient stringifiés en joignant leurs éléments stringifiés à l'aide de Array.join
au lieu de la concaténation de chaînes pour de meilleures performances.json-stringify
- Cette option supprimera complètement la prise en charge de la validation de schéma dans les grands tableaux . Ce faisant, la surcharge mentionnée précédemment est annulée, améliorant considérablement le temps d'exécution. Attention, il n'y a aucun changement de comportement pour les tableaux qui ne sont pas considérés comme grands La valeur par défaut de largeArraySize
est 20000
. Les valeurs valides pour cela sont des valeurs de type entier, telles que :
20000
2e4
'20000'
'2e4'
- notez que cela sera converti en 2
et non en 20000
1.5
- notez que cela sera converti en 1
Par défaut, la bibliothèque échappe toutes les chaînes. Avec le format « dangereux », la chaîne n'est pas échappée. Cela pose un problème de sécurité potentiellement dangereux. Vous ne pouvez l'utiliser que si vous êtes sûr que vos données n'ont pas besoin d'être échappées. L’avantage est une amélioration significative des performances.
Exemple:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'code' : {
type : 'string' ,
format 'unsafe'
}
}
} )
Pour référence, voici quelques points de référence pour comparer les trois mécanismes. Benchmarks réalisés sur une machine ancienne.
ST1000LM024 HN-M 1TB HDD, Intel Core i7-3610QM @ 2.3GHz, 12GB RAM, 4C/8T
.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)
Traitez la définition du schéma comme du code d'application ; il n'est pas sûr d'utiliser des schémas fournis par l'utilisateur.
Pour obtenir une rédaction à faible coût et hautes performances fast-json-stringify
crée et compile une fonction (à l'aide du constructeur Function
) lors de l'initialisation. Bien que le schema
soit actuellement validé pour détecter toute erreur de développeur, rien ne garantit que la fourniture d'un schéma généré par l'utilisateur ne pourrait pas exposer votre application à des attaques à distance.
Les utilisateurs sont responsables de l'envoi de données fiables. fast-json-stringify
garantit que vous obtiendrez une sortie valide uniquement si votre entrée correspond au schéma ou peut être contrainte au schéma. Si votre entrée ne correspond pas au schéma, vous obtiendrez un comportement indéfini.
Le mode débogage peut être activé lors de votre développement pour comprendre ce qui se passe lorsque les choses ne fonctionnent pas comme prévu.
const debugCompiled = fastJson ( {
title : 'default string' ,
type : 'object' ,
properties : {
firstName : {
type : 'string'
}
}
} , { mode : 'debug' } )
console . log ( debugCompiled ) // it is a object contain code, ajv instance
const rawString = debugCompiled . code // it is the generated code
console . log ( rawString )
const stringify = fastJson . restore ( debugCompiled ) // use the generated string to get back the `stringify` function
console . log ( stringify ( { firstName : 'Foo' , surname : 'bar' } ) ) // '{"firstName":"Foo"}'
Le mode autonome est utilisé pour compiler le code qui peut être directement exécuté par node
lui-même. Vous devez avoir installé fast-json-stringify
pour que le code autonome fonctionne.
const fs = require ( 'fs' )
const code = fastJson ( {
title : 'default string' ,
type : 'object' ,
properties : {
firstName : {
type : 'string'
}
}
} , { mode : 'standalone' } )
fs . writeFileSync ( 'stringify.js' , code )
const stringify = require ( 'stringify.js' )
console . log ( stringify ( { firstName : 'Foo' , surname : 'bar' } ) ) // '{"firstName":"Foo"}'
Ce projet a été aimablement sponsorisé par nearForm.
MIT