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
하도록 제공할 수 있습니다.
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 Object가 아닌 Date 문자열 형식의 경우에는 조작이 없습니다. 올바른 형식이어야 합니다.
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
오류가 발생합니다.
필드가 스키마에 있지만 (필수는 아님) 문자열화할 개체에 없으면 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' }
방식으로 선언된 객체 또는 부울이어야 합니다. 추가 속성은 속성 및 패턴 속성 개체에 명시적으로 나열되지 않은 속성에 대해서만 작동합니다.
externalProperties 가 없거나 false
로 설정된 경우 속성 및 PatternProperties 개체에 명시적으로 나열되지 않은 모든 속성은 누락된 필드에 설명된 대로 무시됩니다. 직렬화하기 전에 객체를 다시 작성하지 않아도 되도록 누락된 필드는 무시됩니다. 그러나 다른 스키마 규칙에서도 비슷한 상황이 발생합니다. externalProperties가 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}
NB 속성을 두 번 선언하지 마십시오. 그렇지 않으면 두 번 인쇄됩니다!
값 정의를 재사용하려면 $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
- 이 옵션은 이 lib에서 예상되는 기능을 계속 제공하지만 일부 가능한 성능 향상을 포기함으로써 성능과 기능 세트 간의 절충안입니다. 이 옵션을 설정하면 더 나은 성능을 위해 문자열 연결 대신 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'
}
}
} )
참고로 다음은 세 가지 메커니즘을 비교하기 위한 몇 가지 벤치마크입니다. 오래된 시스템에서 수행된 벤치마크입니다.
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의 친절한 후원을 받았습니다.
MIT