fast-json-stringify は、小さなペイロードの場合、 JSON.stringify()
よりも大幅に高速です。ペイロードが増加するにつれて、そのパフォーマンス上の利点は減少します。これは、最終的に文字列をBuffer
に変換する際のパフォーマンスを向上させる V8 最適化をトリガーするflatstrとよく組み合わせます。
fast-json-stringify では、高速stringify
関数を生成するために JSON Schema Draft 7 入力が必要です。
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
とOneOf
Reuse - $ref
Long integers
Integers
Nullable
Large Arrays
Security Notice
Debug Mode
Standalone Mode
Acknowledgements
License
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 : / "([^"]|\")*" /
} ) )
オプションで、 fast-json-stringify
にオプション オブジェクトを 2 番目のパラメーターとして指定できます。
const fastJson = require ( 'fast-json-stringify' )
const stringify = fastJson ( mySchema , {
schema : { ... } ,
ajv : { ... } ,
rounding : 'ceil'
} )
schema
: $ref プロパティによる外部スキーマ参照。さらに詳しくajv
: ajv
必要とするプロパティの ajv v8 インスタンスの設定。さらに詳しくrounding
: integer
型が整数でない場合にどのように丸めるかを設定します。さらに詳しくlargeArrayMechanism
: 大きな (デフォルトでは20000
以上の項目) 配列を処理するために使用するメカニズムを設定します。さらに詳しく jsonschema ドラフト 7 仕様に基づいてstringify()
関数を構築します。
サポートされているタイプ:
'string'
'integer'
'number'
'array'
'object'
'boolean'
'null'
ネストされたものも。
実例 | として連載 |
---|---|
Date | toISOString() 経由のstring |
RegExp | string |
BigInt | toString 経由のinteger |
JSON スキーマの組み込み日付形式がサポートされており、次のようにシリアル化されます。
形式 | シリアル化された形式の例 |
---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
注: 日付オブジェクトではなく文字列形式の日付の場合、操作は行われません。正しくフォーマットされている必要があります。
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"'
スキーマ内のrequired
配列内にフィールド名を追加することで、スキーマ内の必要に応じてオブジェクトの特定のフィールドを設定できます。例:
const schema = {
title : 'Example Schema with required field' ,
type : 'object' ,
properties : {
nickname : {
type : 'string'
} ,
mail : {
type : 'string'
}
} ,
required : [ 'mail' ]
}
文字列化するオブジェクトに必要なフィールドが欠落している場合、 fast-json-stringify
エラーをスローします。
フィールドがスキーマに存在し(必須ではない)、stringify するオブジェクトに存在しない場合、 fast-json-stringify
それを最終文字列に書き込みません。例:
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
値がundefined
または存在しない場合に値をシリアル化するためにdefault
jsonschema キーをサポートします。
例:
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
JSON スキーマで定義されたパターン プロパティをサポートします。 patternProperties はオブジェクトである必要があります。キーは有効な正規表現、値はオブジェクトであり、次のように宣言されます: { type: 'type' }
。 patternProperties は、プロパティ オブジェクトに明示的にリストされていないプロパティに対してのみ機能します。例:
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
JSON スキーマで定義されている追加のプロパティをサポートします。 addedProperties は、 { type: 'type' }
のように宣言されたオブジェクトまたはブール値である必要があります。 addedProperties は、 properties オブジェクトとpatternPropertiesオブジェクトに明示的にリストされていないプロパティに対してのみ機能します。
addedPropertiesが存在しないか、 false
に設定されている場合、プロパティおよびpatternPropertiesオブジェクトに明示的にリストされていないすべてのプロパティは、「欠落しているフィールド」で説明されているように無視されます。シリアル化する前にオブジェクトを書き直す必要がないように、欠落しているフィールドは無視されます。ただし、他のスキーマ ルールでも同様の状況が発生します。 addedPropertiesがtrue
に設定されている場合、追加のプロパティを文字列化するためにJSON.stringify
によって使用されます。最大のパフォーマンスを達成したい場合は、可能な限り固定スキーマを使用することを強くお勧めします。追加のプロパティは常にオブジェクトの最後でシリアル化されます。例:
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
JSON スキーマで定義されているanyOfキーワードとoneOfキーワードをサポートします。どちらも有効な JSON スキーマの配列である必要があります。さまざまなスキーマが指定された順序でテストされます。 stringify
一致するものを見つける前に試行しなければならないスキーマが多いほど、速度は遅くなります。
anyOfとoneOf は、データに一致するスキーマを見つけるための JSON スキーマ検証ツールとして ajv を使用します。これはパフォーマンスに影響を与えるため、最後の手段としてのみ使用してください。
例:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'undecidedType' : {
'anyOf' : [ {
type : 'string'
} , {
type : 'boolean'
} ]
}
}
} )
anyOfにオブジェクト JSON スキーマを指定する場合は、必要なプロパティを持つオブジェクトのみと一致するように必須の検証キーワードを追加します。
例:
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
if/then/else
jsonschema 機能をサポートします。 ajv のドキュメントを参照してください。
例:
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}
注意プロパティを 2 回宣言しないでください。宣言すると、プロパティが 2 回出力されてしまいます。
値の定義を再利用したい場合は、プロパティ$ref
使用できます。 $ref
の値は、JSON ポインター形式の文字列である必要があります。例:
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 )
外部定義を使用する必要がある場合は、それをオプションとしてfast-json-stringify
に渡すことができます。例:
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 } )
外部定義は相互に参照することもできます。例:
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 } )
デフォルトでは、ライブラリは BigInt を自動的に処理します。
type: integer
プロパティは、浮動小数点が指定された場合に切り捨てられます。この動作は、 round
、 ceil
、 floor
、またはtrunc
受け入れるrounding
オプションを使用してカスタマイズできます。デフォルトはtrunc
です。
const stringify = fastJson ( schema , { rounding : 'ceil' } )
Open API 3.0 仕様によれば、null にできる値は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
それ以外の場合は、エラーが発生する代わりに、次のように null 値が強制されます。
integer
-> 0
number
-> 0
string
-> ""
boolean
-> false
object
-> {}
array
-> []
このドキュメントの範囲では、大規模な配列は、デフォルトで20000
以上の要素を含む配列として定義されます。この値は、オプション パラメーターlargeArraySize
を介して調整できます。
ある時点から、配列を処理するためにfast-json-stringify
によって使用されるデフォルトのメカニズムによって生じるオーバーヘッドが指数関数的に増加し始め、全体的な実行が遅くなります。
これを改善するために、ユーザーはlargeArrayMechanism
およびlargeArraySize
オプションを設定できます。
largeArrayMechanism
のデフォルト値は、 default
です。有効な値は次のとおりです。
default
- このオプションは、このライブラリから期待される機能を引き続き提供しますが、可能性のあるパフォーマンスの向上をある程度諦めることにより、パフォーマンスと機能セットの間の妥協策です。このオプションを設定すると、パフォーマンスを向上させるために、文字列連結の代わりにArray.join
使用して文字列化された要素を結合することによって、大きな配列が文字列化されます。json-stringify
- このオプションは、大規模な配列内のスキーマ検証のサポートを完全に削除します。これにより、前述のオーバーヘッドがゼロになり、実行時間が大幅に改善されます。大きいと見なされない配列の動作に変更はないことに注意してください。 largeArraySize
のデフォルト値は20000
です。有効な値は、次のような整数値です。
20000
2e4
'20000'
'2e4'
-これは20000
ではなく2
に変換されることに注意してください1.5
-これは1
に変換されることに注意してくださいデフォルトでは、ライブラリはすべての文字列をエスケープします。 「安全でない」形式では、文字列はエスケープされません。これには潜在的に危険なセキュリティ上の問題があります。データをエスケープする必要がないことが確実な場合にのみ使用できます。利点は、パフォーマンスが大幅に向上することです。
例:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'code' : {
type : 'string' ,
format 'unsafe'
}
}
} )
参考までに、3 つのメカニズムを比較するためのベンチマークをいくつか示します。ベンチマークは古いマシンで実施されました。
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)
スキーマ定義をアプリケーション コードとして扱います。ユーザーが提供したスキーマを使用するのは安全ではありません。
低コストで高パフォーマンスの編集を実現するために、 fast-json-stringify
初期化時に ( Function
コンストラクターを使用して) 関数を作成してコンパイルします。現在、 schema
は開発者のエラーがないか検証されていますが、ユーザーが生成したスキーマを提供することでアプリケーションがリモート攻撃にさらされないという保証はありません。
ユーザーは信頼できるデータを送信する責任があります。 fast-json-stringify
入力がスキーマに一致するか、スキーマに強制できる場合にのみ、有効な出力が得られることを保証します。入力がスキーマと一致しない場合、未定義の動作が発生します。
デバッグ モードは、開発中にアクティブ化して、期待どおりに動作しない場合に何が起こっているかを理解できます。
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"}'
スタンドアロン モードは、 node
自体で直接実行できるコードをコンパイルするために使用されます。スタンドアロン コードが機能するには、 fast-json-stringify
インストールする必要があります。
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"}'
このプロジェクトはnearFormのご厚意により後援していただきました。
マサチューセッツ工科大学