fast-json-stringify ist bei kleinen Nutzlasten deutlich schneller als JSON.stringify()
. Sein Leistungsvorteil nimmt mit zunehmender Nutzlast ab. Es lässt sich gut mit flatstr kombinieren, das eine V8-Optimierung auslöst, die die Leistung verbessert, wenn der String schließlich in einen Buffer
konvertiert wird.
fast-json-stringify erfordert eine JSON Schema Draft 7-Eingabe, um eine schnelle stringify
Funktion zu generieren.
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
und OneOf
Reuse - $ref
Long integers
Integers
Nullable
Large Arrays
Security Notice
Debug Mode
Standalone Mode
Acknowledgements
License
Probieren Sie es auf RunKit aus: 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 : / "([^"]|\")*" /
} ) )
Optional können Sie als zweiten Parameter ein Optionsobjekt zur fast-json-stringify
bereitstellen:
const fastJson = require ( 'fast-json-stringify' )
const stringify = fastJson ( mySchema , {
schema : { ... } ,
ajv : { ... } ,
rounding : 'ceil'
} )
schema
: Referenzen auf externe Schemata durch die Eigenschaft $ref. Weitere Detailsajv
: Einstellungen der ajv v8-Instanz für die Eigenschaften, die ajv
erfordern. Weitere Detailsrounding
: Richten Sie ein, wie die integer
gerundet werden, wenn es sich nicht um Ganzzahlen handelt. Weitere DetailslargeArrayMechanism
: Legen Sie den Mechanismus fest, der zur Verarbeitung großer Arrays (standardmäßig 20000
oder mehr Elemente) verwendet werden soll. Weitere Details Erstellen Sie eine stringify()
Funktion basierend auf der Jsonschema Draft 7-Spezifikation.
Unterstützte Typen:
'string'
'integer'
'number'
'array'
'object'
'boolean'
'null'
Und auch verschachtelte.
Beispiel | Serialisiert als |
---|---|
Date | string über toISOString() |
RegExp | string |
BigInt | integer über toString |
Integrierte JSON-Schema-Formate für Datumsangaben werden unterstützt und wie folgt serialisiert:
Format | Beispiel für ein serialisiertes Format |
---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
Hinweis : Im Fall eines als Zeichenfolge formatierten Datums und nicht eines Datumsobjekts erfolgt keine Manipulation daran. Es sollte richtig formatiert sein.
Beispiel mit einem Date-Objekt:
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"'
Sie können bestimmte Felder eines Objekts nach Bedarf in Ihrem Schema festlegen, indem Sie den Feldnamen in das required
Array in Ihrem Schema einfügen. Beispiel:
const schema = {
title : 'Example Schema with required field' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
} ,
mail : {
type : 'string'
}
} ,
required : [ 'mail' ]
}
Wenn dem zu stringifizierenden Objekt die erforderlichen Felder fehlen, gibt fast-json-stringify
einen Fehler aus.
Wenn ein Feld im Schema vorhanden ist (und nicht erforderlich ist), aber nicht im zu stringifizierenden Objekt vorhanden ist , schreibt fast-json-stringify
es nicht in die endgültige Zeichenfolge. Beispiel:
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
unterstützt default
-Jsonschema-Schlüssel, um einen Wert zu serialisieren, wenn er undefined
oder nicht vorhanden ist.
Beispiel:
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
unterstützt Mustereigenschaften, wie sie im JSON-Schema definiert sind. patternProperties muss ein Objekt sein, wobei der Schlüssel ein gültiger regulärer Ausdruck und der Wert ein Objekt ist, das auf diese Weise deklariert wird: { type: 'type' }
. „patternProperties“ funktioniert nur für die Eigenschaften, die nicht explizit im Eigenschaftenobjekt aufgeführt sind. Beispiel:
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
unterstützt zusätzliche Eigenschaften, wie durch das JSON-Schema definiert. „additionalProperties“ muss ein Objekt oder ein boolescher Wert sein und auf diese Weise deklariert werden: { type: 'type' }
. „additionalProperties“ funktioniert nur für die Eigenschaften, die nicht explizit in den Objekten „properties“ und „patternProperties“ aufgeführt sind.
Wenn „additionalProperties“ nicht vorhanden oder auf false
gesetzt ist, wird jede Eigenschaft, die nicht explizit in den Objekten „properties“ und „patternProperties“ aufgeführt ist, ignoriert, wie unter „Fehlende Felder“ beschrieben. Fehlende Felder werden ignoriert, um zu vermeiden, dass Objekte vor der Serialisierung neu geschrieben werden müssen. Andere Schemaregeln würden jedoch ähnliche Situationen auslösen. Wenn „additionalProperties“ auf true
gesetzt ist, wird es von JSON.stringify
verwendet, um die zusätzlichen Eigenschaften in Strings umzuwandeln. Wenn Sie maximale Leistung erzielen möchten, empfehlen wir Ihnen dringend, nach Möglichkeit ein festes Schema zu verwenden. Die zusätzlichen Eigenschaften werden immer am Ende des Objekts serialisiert. Beispiel:
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
unterstützt die Schlüsselwörter „anyOf“ und „oneOf“ , wie im JSON-Schema definiert. Bei beiden muss es sich um ein Array gültiger JSON-Schemas handeln. Die verschiedenen Schemata werden in der angegebenen Reihenfolge getestet. Je mehr Schemata stringify
ausprobieren muss, bevor eine Übereinstimmung gefunden wird, desto langsamer wird es.
anyOf und oneOf verwenden ajv als JSON-Schema-Validator, um das Schema zu finden, das mit den Daten übereinstimmt. Dies wirkt sich auf die Leistung aus – verwenden Sie es daher nur als letzten Ausweg.
Beispiel:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'undecidedType' : {
'anyOf' : [ {
type : 'string'
} , {
type : 'boolean'
} ]
}
}
} )
Wenn Sie Objekt-JSON-Schemas für anyOf angeben, fügen Sie das erforderliche Validierungsschlüsselwort hinzu, um nur die Objekte mit den gewünschten Eigenschaften abzugleichen.
Beispiel:
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
unterstützt if/then/else
-Jsonschema-Funktion. Siehe AJV-Dokumentation.
Beispiel:
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}
Hinweis: Deklarieren Sie die Eigenschaften nicht zweimal, sonst werden sie zweimal gedruckt!
Wenn Sie eine Definition eines Werts wiederverwenden möchten, können Sie die Eigenschaft $ref
verwenden. Der Wert von $ref
muss eine Zeichenfolge im JSON-Zeigerformat sein. Beispiel:
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 )
Wenn Sie eine externe Definition verwenden müssen, können Sie diese als Option an fast-json-stringify
übergeben. Beispiel:
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 } )
Auch externe Definitionen können aufeinander verweisen. Beispiel:
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 } )
Standardmäßig verarbeitet die Bibliothek BigInt automatisch.
Die Eigenschaft type: integer
wird abgeschnitten, wenn ein Gleitkommawert angegeben wird. Sie können dieses Verhalten mit der rounding
anpassen, die round
“, ceil
, floor
und trunc
akzeptiert. Der Standardwert ist trunc
:
const stringify = fastJson ( schema , { rounding : 'ceil' } )
Gemäß der Open API 3.0-Spezifikation muss ein Wert, der null sein kann, nullable
deklariert werden.
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
Andernfalls werden Nullwerte wie folgt erzwungen, anstatt einen Fehler auszulösen:
integer
-> 0
number
-> 0
string
-> ""
boolean
-> false
object
-> {}
array
-> []
Große Arrays werden im Rahmen dieses Dokuments als Arrays definiert, die standardmäßig 20000
Elemente oder mehr enthalten. Dieser Wert kann über den Optionsparameter largeArraySize
angepasst werden.
Irgendwann beginnt der Overhead, der durch den von fast-json-stringify
zur Verarbeitung von Arrays verwendeten Standardmechanismus verursacht wird, exponentiell anzusteigen, was zu insgesamt langsamen Ausführungen führt.
Um dies zu verbessern, kann der Benutzer die Optionen largeArrayMechanism
und largeArraySize
festlegen.
Der Standardwert von largeArrayMechanism
ist default
. Gültige Werte dafür sind:
default
– Diese Option stellt einen Kompromiss zwischen Leistung und Funktionsumfang dar, indem sie immer noch die erwartete Funktionalität dieser Bibliothek bereitstellt, aber auf einen möglichen Leistungsgewinn verzichtet. Wenn diese Option festgelegt ist, werden große Arrays für eine bessere Leistung in Strings umgewandelt, indem ihre String-Elemente mithilfe von Array.join
anstelle der String-Verkettung verbunden werdenjson-stringify
– Diese Option entfernt die Unterstützung für die Schemavalidierung innerhalb großer Arrays vollständig. Dadurch wird der zuvor erwähnte Overhead aufgehoben, was die Ausführungszeit erheblich verkürzt. Beachten Sie, dass sich das Verhalten für Arrays, die nicht als groß gelten, nicht ändert Der Standardwert von largeArraySize
ist 20000
. Gültige Werte dafür sind ganzzahlige Werte, wie zum Beispiel:
20000
2e4
'20000'
'2e4'
– beachten Sie, dass dies in 2
und nicht in 20000
konvertiert wird1.5
– beachten Sie, dass dies in 1
umgewandelt wird Standardmäßig maskiert die Bibliothek alle Zeichenfolgen. Beim „unsicheren“ Format wird die Zeichenfolge nicht maskiert. Dies stellt ein potenziell gefährliches Sicherheitsproblem dar. Sie können es nur verwenden, wenn Sie sicher sind, dass Ihre Daten nicht verschlüsselt werden müssen. Der Vorteil ist eine deutliche Leistungssteigerung.
Beispiel:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'code' : {
type : 'string' ,
format 'unsafe'
}
}
} )
Als Referenz finden Sie hier einige Benchmarks zum Vergleich der drei Mechanismen. Benchmarks wurden auf einer alten Maschine durchgeführt.
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)
Behandeln Sie die Schemadefinition als Anwendungscode. Die Verwendung vom Benutzer bereitgestellter Schemata ist nicht sicher.
Um eine kostengünstige und leistungsstarke Schwärzung zu erreichen, erstellt und kompiliert fast-json-stringify
bei der Initialisierung eine Funktion (mit dem Function
). Obwohl das schema
derzeit auf Entwicklerfehler überprüft wird, gibt es keine Garantie dafür, dass die Bereitstellung eines benutzergenerierten Schemas Ihre Anwendung nicht Remote-Angriffen aussetzen kann.
Benutzer sind für die Übermittlung vertrauenswürdiger Daten verantwortlich. fast-json-stringify
garantiert, dass Sie nur dann eine gültige Ausgabe erhalten, wenn Ihre Eingabe mit dem Schema übereinstimmt oder in das Schema gezwungen werden kann. Wenn Ihre Eingabe nicht mit dem Schema übereinstimmt, erhalten Sie undefiniertes Verhalten.
Der Debug-Modus kann während Ihrer Entwicklung aktiviert werden, um zu verstehen, was passiert, wenn etwas nicht wie erwartet funktioniert.
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"}'
Der Standalone-Modus wird zum Kompilieren des Codes verwendet, der direkt vom node
selbst ausgeführt werden kann. Damit der eigenständige Code funktioniert, muss fast-json-stringify
installiert sein.
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"}'
Dieses Projekt wurde freundlicherweise von nearForm gesponsert.
MIT