對於小負載, fast-json-stringify比JSON.stringify()
快得多。隨著有效負載的增加,其效能優勢會縮小。它與flatstr配合得很好,後者會觸發 V8 優化,從而在最終將字串轉換為Buffer
時提高效能。
fast-json-stringify 需要 JSON Schema Draft 7 輸入來產生快速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
和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
提供一個選項物件作為第二個參數:
const fastJson = require ( 'fast-json-stringify' )
const stringify = fastJson ( mySchema , {
schema : { ... } ,
ajv : { ... } ,
rounding : 'ceil'
} )
schema
:透過 $ref 屬性引用外部模式。更多詳情ajv
:ajv v8 實例的那些需要ajv
屬性的設定。更多詳情rounding
:設定integer
類型在非整數時如何四捨五入。更多詳情largeArrayMechanism
:設定用於處理大型(預設為20000
或更多項)陣列的機制。更多詳情基於 jsonschema 草案 7 規範建構stringify()
函數。
支援的類型:
'string'
'integer'
'number'
'array'
'object'
'boolean'
'null'
還有嵌套的。
實例 | 序列化為 |
---|---|
Date | 透過toISOString() string |
RegExp | string |
BigInt | 透過toString integer |
支援 JSON Schema 內建日期格式,並將序列化為:
格式 | 序列化格式範例 |
---|---|
date-time | 2020-04-03T09:11:08.615Z |
date | 2020-04-03 |
time | 09:11:08 |
注意:如果是字串格式的日期而不是日期對象,則不會對其進行任何操作。它應該被正確格式化。
日期物件範例:
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' ]
}
如果要 stringify 的物件缺少必需的字段, fast-json-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
支援default
jsonschema 鍵,以便在undefined
或不存在的情況下序列化值。
例子:
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 模式定義的其他屬性。 extraProperties必須是一個物件或布林值,以這種方式宣告: { type: 'type' }
。 extraProperties僅適用於properties和patternProperties物件中未明確列出的屬性。
如果additionalProperties不存在或設定為false
,則屬性和patternProperties物件中未明確列出的每個屬性都將被忽略,如缺少欄位所述。缺少的欄位將被忽略,以避免在序列化之前重寫物件。然而,其他模式規則也會引發類似的情況。如果extraProperties設定為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使用 ajv 作為 JSON 模式驗證器來尋找與資料相符的模式。這會對性能產生影響——僅將其用作最後的手段。
例子:
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}
注意不要聲明屬性兩次,否則您將列印兩次!
如果要重複使用值的定義,可以使用屬性$ref
。 $ref
的值必須是 JSON Pointer 格式的字串。例子:
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'
-請注意這將轉換為2
,而不是20000
1.5
-請注意這將轉換為1
預設情況下,該程式庫會對所有字串進行轉義。使用“不安全”格式,字串不會被轉義。這存在潛在危險的安全問題。僅當您確定資料不需要轉義時才可以使用它。優點是性能顯著提高。
例子:
const stringify = fastJson ( {
title : 'Example Schema' ,
type : 'object' ,
properties : {
'code' : {
type : 'string' ,
format 'unsafe'
}
}
} )
作為參考,這裡有一些對三種機制進行比較的基準。在舊機器上進行的基準測試。
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"}'
Standalone模式用於編譯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 的大力贊助。
麻省理工學院