fast-json-stringify es significativamente más rápido que JSON.stringify()
para cargas pequeñas. Su ventaja de rendimiento se reduce a medida que crece su carga útil. Se combina bien con flatstr , que activa una optimización V8 que mejora el rendimiento cuando finalmente se convierte la cadena en un Buffer
.
fast-json-stringify requiere una entrada JSON Schema Draft 7 para generar una función stringify
rápida.
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
y OneOf
Reuse - $ref
Long integers
Integers
Nullable
Large Arrays
Security Notice
Debug Mode
Standalone Mode
Acknowledgements
License
Pruébelo en 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 : / "([^"]|\")*" /
} ) )
Opcionalmente, puede proporcionar fast-json-stringify
un objeto de opción como segundo parámetro:
const fastJson = require ( 'fast-json-stringify' )
const stringify = fastJson ( mySchema , {
schema : { ... } ,
ajv : { ... } ,
rounding : 'ceil'
} )
schema
: referencias de esquemas externos por propiedad $ref. Más detallesajv
: configuración de la instancia de ajv v8 para aquellas propiedades que requieren ajv
. Más detallesrounding
: configura cómo se redondearán los tipos integer
cuando no sean enteros. Más detalleslargeArrayMechanism
: establece el mecanismo que se debe utilizar para manejar matrices grandes (por defecto, 20000
o más elementos). Más detalles Cree una función stringify()
basada en la especificación jsonschema draft 7.
Tipos soportados:
'string'
'integer'
'number'
'array'
'object'
'boolean'
'null'
Y también los anidados.
Instancia | Serializado como |
---|---|
Date | string a través de toISOString() |
RegExp | string |
BigInt | integer a través de toString |
Los formatos integrados de JSON Schema para fechas son compatibles y se serializarán como:
Formato | Ejemplo de formato serializado |
---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
Nota : En el caso de una cadena con formato de fecha y no de un objeto de fecha, no habrá ninguna manipulación. Debe tener el formato adecuado.
Ejemplo con un objeto Fecha:
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"'
Puede configurar campos específicos de un objeto según sea necesario en su esquema agregando el nombre del campo dentro de la matriz required
en su esquema. Ejemplo:
const schema = {
title : 'Example Schema with required field' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
} ,
mail : {
type : 'string'
}
} ,
required : [ 'mail' ]
}
Si al objeto a encadenar le faltan los campos requeridos, fast-json-stringify
arrojará un error.
Si un campo está presente en el esquema (y no es obligatorio) pero no está presente en el objeto a encadenar, fast-json-stringify
no lo escribirá en la cadena final. Ejemplo:
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
admite la clave jsonschema default
para serializar un valor si undefined
está definido o no está presente.
Ejemplo:
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
admite propiedades de patrón según lo definido por el esquema JSON. PatternProperties debe ser un objeto, donde la clave es una expresión regular válida y el valor es un objeto, declarado de esta manera: { type: 'type' }
. PatternProperties funcionará solo para las propiedades que no se enumeran explícitamente en el objeto de propiedades. Ejemplo:
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
admite propiedades adicionales según lo definido por el esquema JSON. adicionalProperties debe ser un objeto o un valor booleano, declarado de esta manera: { type: 'type' }
. adicionalProperties funcionará solo para las propiedades que no se enumeran explícitamente en los objetos de propiedades y patrónProperties .
Si adicionalProperties no está presente o se establece en false
, todas las propiedades que no estén enumeradas explícitamente en los objetos properties y patrónProperties se ignorarán, como se describe en Campos faltantes. Los campos faltantes se ignoran para evitar tener que reescribir los objetos antes de serializarlos. Sin embargo, otras reglas de esquema se producirían en situaciones similares. Si adicionalProperties se establece en true
, JSON.stringify
lo utilizará para encadenar las propiedades adicionales. Si desea lograr el máximo rendimiento, le recomendamos encarecidamente que utilice un esquema fijo siempre que sea posible. Las propiedades adicionales siempre se serializarán al final del objeto. Ejemplo:
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
admite las palabras clave anyOf y oneOf según lo definido por el esquema JSON. Ambos deben ser una matriz de esquemas JSON válidos. Los diferentes esquemas se probarán en el orden especificado. Cuantos más esquemas tenga que probar stringify
antes de encontrar una coincidencia, más lento será.
anyOf y oneOf usan ajv como validador de esquema JSON para encontrar el esquema que coincide con los datos. Esto tiene un impacto en el rendimiento; utilícelo sólo como último recurso.
Ejemplo:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'undecidedType' : {
'anyOf' : [ {
type : 'string'
} , {
type : 'boolean'
} ]
}
}
} )
Al especificar esquemas JSON de objetos para anyOf , agregue la palabra clave de validación requerida para hacer coincidir solo los objetos con las propiedades que desea.
Ejemplo:
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
admite la función if/then/else
jsonschema. Consulte la documentación de ajv.
Ejemplo:
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 ¡No declares las propiedades dos veces o las imprimirás dos veces!
Si desea reutilizar una definición de un valor, puede utilizar la propiedad $ref
. El valor de $ref
debe ser una cadena en formato de puntero JSON. Ejemplo:
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 necesita utilizar una definición externa, puede pasarla como una opción a fast-json-stringify
. Ejemplo:
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 } )
Las definiciones externas también pueden hacer referencia entre sí. Ejemplo:
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 } )
De forma predeterminada, la biblioteca manejará automáticamente BigInt.
La propiedad type: integer
se truncará si se proporciona un punto flotante. Puede personalizar este comportamiento con la opción rounding
que aceptará round
, ceil
, floor
o trunc
. El valor predeterminado es trunc
:
const stringify = fastJson ( schema , { rounding : 'ceil' } )
Según la especificación Open API 3.0, un valor que puede ser nulo debe declararse 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
De lo contrario, en lugar de generar un error, los valores nulos se forzarán de la siguiente manera:
integer
-> 0
number
-> 0
string
-> ""
boolean
-> false
object
-> {}
array
-> []
Para el alcance de este documento, las matrices grandes se definen como matrices que contienen, de forma predeterminada, 20000
elementos o más. Ese valor se puede ajustar mediante el parámetro de opción largeArraySize
.
En algún momento, la sobrecarga causada por el mecanismo predeterminado utilizado por fast-json-stringify
para manejar matrices comienza a aumentar exponencialmente, lo que lleva a ejecuciones generales lentas.
Para mejorar eso, el usuario puede configurar las opciones largeArrayMechanism
y largeArraySize
.
El valor predeterminado de largeArrayMechanism
es default
. Los valores válidos para ello son:
default
: esta opción es un compromiso entre el rendimiento y el conjunto de funciones al seguir proporcionando la funcionalidad esperada de esta biblioteca pero renunciando a una posible ganancia de rendimiento. Con esta opción configurada, las matrices grandes se encadenarían uniendo sus elementos encadenados usando Array.join
en lugar de la concatenación de cadenas para un mejor rendimiento.json-stringify
: esta opción eliminará por completo la compatibilidad con la validación de esquemas dentro de matrices grandes . Al hacerlo, se anula la sobrecarga mencionada anteriormente, lo que mejora enormemente el tiempo de ejecución. Tenga en cuenta que no hay cambios en el comportamiento de las matrices que no se consideran grandes El valor predeterminado de largeArraySize
es 20000
. Los valores válidos para ello son valores de tipo entero, como por ejemplo:
20000
2e4
'20000'
'2e4'
- tenga en cuenta que esto se convertirá a 2
, no 20000
1.5
- tenga en cuenta que esto se convertirá a 1
De forma predeterminada, la biblioteca escapa de todas las cadenas. Con el formato "inseguro", la cadena no tiene escape. Esto tiene un problema de seguridad potencialmente peligroso. Puede usarlo solo si está seguro de que no es necesario escapar sus datos. La ventaja es una mejora significativa del rendimiento.
Ejemplo:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'code' : {
type : 'string' ,
format 'unsafe'
}
}
} )
Como referencia, aquí hay algunos puntos de referencia para comparar los tres mecanismos. Puntos de referencia realizados en una máquina antigua.
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)
Trate la definición del esquema como código de aplicación; no es seguro utilizar esquemas proporcionados por el usuario.
Para lograr una redacción de bajo costo y alto rendimiento fast-json-stringify
crea y compila una función (usando el constructor Function
) en la inicialización. Si bien el schema
está actualmente validado para detectar errores del desarrollador, no hay garantía de que proporcionar un esquema generado por el usuario no exponga su aplicación a ataques remotos.
Los usuarios son responsables de enviar datos confiables. fast-json-stringify
garantiza que obtendrá una salida válida solo si su entrada coincide con el esquema o puede ser forzada al esquema. Si su entrada no coincide con el esquema, obtendrá un comportamiento indefinido.
El modo de depuración se puede activar durante el desarrollo para comprender qué sucede cuando las cosas no funcionan como se esperaba.
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"}'
El modo independiente se utiliza para compilar el código que el propio node
puede ejecutar directamente. Debe tener instalado fast-json-stringify
para que funcione el código independiente.
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"}'
Este proyecto fue patrocinado amablemente por nearForm.
MIT