fast-json-stringify 2.7.9 → 2.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +4 -0
- package/.github/workflows/benchmark.yml +111 -0
- package/.github/workflows/ci.yml +3 -3
- package/README.md +13 -10
- package/bench.js +28 -0
- package/index.js +54 -17
- package/package.json +1 -1
- package/test/allof.test.js +52 -0
- package/test/recursion.test.js +180 -0
package/.github/dependabot.yml
CHANGED
|
@@ -2,6 +2,10 @@ version: 2
|
|
|
2
2
|
updates:
|
|
3
3
|
- package-ecosystem: github-actions
|
|
4
4
|
directory: '/'
|
|
5
|
+
ignore:
|
|
6
|
+
- dependency-name: "actions/*"
|
|
7
|
+
update-types:
|
|
8
|
+
["version-update:semver-minor", "version-update:semver-patch"]
|
|
5
9
|
schedule:
|
|
6
10
|
interval: daily
|
|
7
11
|
open-pull-requests-limit: 10
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
name: Benchmark
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types: [labeled]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
benchmark:
|
|
9
|
+
if: ${{ github.event.label.name == 'benchmark' }}
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
outputs:
|
|
12
|
+
PR-BENCH-12: ${{ steps.benchmark-pr.outputs.BENCH_RESULT12 }}
|
|
13
|
+
PR-BENCH-14: ${{ steps.benchmark-pr.outputs.BENCH_RESULT14 }}
|
|
14
|
+
PR-BENCH-16: ${{ steps.benchmark-pr.outputs.BENCH_RESULT16 }}
|
|
15
|
+
MAIN-BENCH-12: ${{ steps.benchmark-main.outputs.BENCH_RESULT12 }}
|
|
16
|
+
MAIN-BENCH-14: ${{ steps.benchmark-main.outputs.BENCH_RESULT14 }}
|
|
17
|
+
MAIN-BENCH-16: ${{ steps.benchmark-main.outputs.BENCH_RESULT16 }}
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
node-version: [12, 14, 16]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v2
|
|
23
|
+
with:
|
|
24
|
+
ref: ${{github.event.pull_request.head.ref}}
|
|
25
|
+
repository: ${{github.event.pull_request.head.repo.full_name}}
|
|
26
|
+
|
|
27
|
+
- uses: actions/setup-node@v2
|
|
28
|
+
with:
|
|
29
|
+
node-version: ${{ matrix.node-version }}
|
|
30
|
+
|
|
31
|
+
- name: Install
|
|
32
|
+
run: |
|
|
33
|
+
npm install --ignore-scripts
|
|
34
|
+
|
|
35
|
+
- name: Run benchmark
|
|
36
|
+
id: benchmark-pr
|
|
37
|
+
run: |
|
|
38
|
+
npm run --silent benchmark > ./bench-result
|
|
39
|
+
content=$(cat ./bench-result)
|
|
40
|
+
content="${content//'%'/'%25'}"
|
|
41
|
+
content="${content//$'\n'/'%0A'}"
|
|
42
|
+
content="${content//$'\r'/'%0D'}"
|
|
43
|
+
echo "::set-output name=BENCH_RESULT${{matrix.node-version}}::$content"
|
|
44
|
+
|
|
45
|
+
# main benchmark
|
|
46
|
+
- uses: actions/checkout@v2
|
|
47
|
+
with:
|
|
48
|
+
ref: 'master'
|
|
49
|
+
|
|
50
|
+
- name: Install
|
|
51
|
+
run: |
|
|
52
|
+
npm install --ignore-scripts
|
|
53
|
+
|
|
54
|
+
- name: Run benchmark
|
|
55
|
+
id: benchmark-master
|
|
56
|
+
run: |
|
|
57
|
+
npm run --silent benchmark > ./bench-result
|
|
58
|
+
content=$(cat ./bench-result)
|
|
59
|
+
content="${content//'%'/'%25'}"
|
|
60
|
+
content="${content//$'\n'/'%0A'}"
|
|
61
|
+
content="${content//$'\r'/'%0D'}"
|
|
62
|
+
echo "::set-output name=BENCH_RESULT${{matrix.node-version}}::$content"
|
|
63
|
+
|
|
64
|
+
output-benchmark:
|
|
65
|
+
needs: [benchmark]
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
steps:
|
|
68
|
+
- name: Comment PR
|
|
69
|
+
uses: thollander/actions-comment-pull-request@v1
|
|
70
|
+
with:
|
|
71
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
72
|
+
message: |
|
|
73
|
+
**Node**: 12
|
|
74
|
+
**PR**:
|
|
75
|
+
```
|
|
76
|
+
${{ needs.benchmark.outputs.PR-BENCH-12 }}
|
|
77
|
+
```
|
|
78
|
+
**MAIN**:
|
|
79
|
+
```
|
|
80
|
+
${{ needs.benchmark.outputs.MAIN-BENCH-12 }}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
**Node**: 14
|
|
86
|
+
**PR**:
|
|
87
|
+
```
|
|
88
|
+
${{ needs.benchmark.outputs.PR-BENCH-14 }}
|
|
89
|
+
```
|
|
90
|
+
**MAIN**:
|
|
91
|
+
```
|
|
92
|
+
${{ needs.benchmark.outputs.MAIN-BENCH-14 }}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
**Node**: 16
|
|
98
|
+
**PR**:
|
|
99
|
+
```
|
|
100
|
+
${{ needs.benchmark.outputs.PR-BENCH-16 }}
|
|
101
|
+
```
|
|
102
|
+
**MAIN**:
|
|
103
|
+
```
|
|
104
|
+
${{ needs.benchmark.outputs.MAIN-BENCH-16 }}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- uses: actions-ecosystem/action-remove-labels@v1
|
|
108
|
+
with:
|
|
109
|
+
labels: |
|
|
110
|
+
benchmark
|
|
111
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -19,10 +19,10 @@ jobs:
|
|
|
19
19
|
os: [macos-latest, ubuntu-latest, windows-latest]
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@v2
|
|
22
|
+
- uses: actions/checkout@v2
|
|
23
23
|
|
|
24
24
|
- name: Use Node.js
|
|
25
|
-
uses: actions/setup-node@v2
|
|
25
|
+
uses: actions/setup-node@v2
|
|
26
26
|
with:
|
|
27
27
|
node-version: ${{ matrix.node-version }}
|
|
28
28
|
|
|
@@ -38,6 +38,6 @@ jobs:
|
|
|
38
38
|
needs: test
|
|
39
39
|
runs-on: ubuntu-latest
|
|
40
40
|
steps:
|
|
41
|
-
- uses: fastify/github-action-merge-dependabot@v2.
|
|
41
|
+
- uses: fastify/github-action-merge-dependabot@v2.7.1
|
|
42
42
|
with:
|
|
43
43
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/README.md
CHANGED
|
@@ -12,22 +12,25 @@ __fast-json-stringify__ is significantly faster than `JSON.stringify()` for smal
|
|
|
12
12
|
##### Benchmarks
|
|
13
13
|
|
|
14
14
|
- Machine: `EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD`.
|
|
15
|
-
- Node.js `
|
|
15
|
+
- Node.js `v16.9.1`
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
FJS creation x
|
|
18
|
+
FJS creation x 6,040 ops/sec ±1.17% (91 runs sampled)
|
|
19
19
|
|
|
20
|
-
JSON.stringify array x 5,
|
|
21
|
-
fast-json-stringify array x
|
|
20
|
+
JSON.stringify array x 5,519 ops/sec ±0.08% (99 runs sampled)
|
|
21
|
+
fast-json-stringify array x 7,143 ops/sec ±0.14% (97 runs sampled)
|
|
22
22
|
|
|
23
|
-
JSON.stringify long string x
|
|
24
|
-
fast-json-stringify long string x
|
|
23
|
+
JSON.stringify long string x 16,438 ops/sec ±0.32% (98 runs sampled)
|
|
24
|
+
fast-json-stringify long string x 16,457 ops/sec ±0.09% (97 runs sampled)
|
|
25
25
|
|
|
26
|
-
JSON.stringify short string x
|
|
27
|
-
fast-json-stringify short string x
|
|
26
|
+
JSON.stringify short string x 12,061,258 ops/sec ±0.32% (97 runs sampled)
|
|
27
|
+
fast-json-stringify short string x 35,531,071 ops/sec ±0.17% (94 runs sampled)
|
|
28
28
|
|
|
29
|
-
JSON.stringify obj x 3,
|
|
30
|
-
fast-json-stringify obj x
|
|
29
|
+
JSON.stringify obj x 3,079,746 ops/sec ±0.09% (95 runs sampled)
|
|
30
|
+
fast-json-stringify obj x 7,721,569 ops/sec ±0.12% (98 runs sampled)
|
|
31
|
+
|
|
32
|
+
JSON stringify date x 1,149,786 ops/sec ±0.10% (99 runs sampled)
|
|
33
|
+
fast-json-stringify date format x 1,674,498 ops/sec ±0.12% (99 runs sampled)
|
|
31
34
|
```
|
|
32
35
|
|
|
33
36
|
#### Table of contents:
|
package/bench.js
CHANGED
|
@@ -50,22 +50,38 @@ const arraySchemaCJS = {
|
|
|
50
50
|
items: schemaCJS
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const dateFormatSchema = {
|
|
54
|
+
description: 'Date of birth',
|
|
55
|
+
type: 'string',
|
|
56
|
+
format: 'date'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const dateFormatSchemaCJS = {
|
|
60
|
+
description: 'Date of birth',
|
|
61
|
+
type: 'string',
|
|
62
|
+
format: 'date'
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
const obj = {
|
|
54
66
|
firstName: 'Matteo',
|
|
55
67
|
lastName: 'Collina',
|
|
56
68
|
age: 32
|
|
57
69
|
}
|
|
58
70
|
|
|
71
|
+
const date = new Date()
|
|
72
|
+
|
|
59
73
|
const multiArray = []
|
|
60
74
|
|
|
61
75
|
const CJS = require('compile-json-stringify')
|
|
62
76
|
const CJSStringify = CJS(schemaCJS)
|
|
63
77
|
const CJSStringifyArray = CJS(arraySchemaCJS)
|
|
78
|
+
const CJSStringifyDate = CJS(dateFormatSchemaCJS)
|
|
64
79
|
const CJSStringifyString = CJS({ type: 'string' })
|
|
65
80
|
|
|
66
81
|
const FJS = require('.')
|
|
67
82
|
const stringify = FJS(schema)
|
|
68
83
|
const stringifyArray = FJS(arraySchema)
|
|
84
|
+
const stringifyDate = FJS(dateFormatSchema)
|
|
69
85
|
const stringifyString = FJS({ type: 'string' })
|
|
70
86
|
let str = ''
|
|
71
87
|
|
|
@@ -138,6 +154,18 @@ suite.add('compile-json-stringify obj', function () {
|
|
|
138
154
|
CJSStringify(obj)
|
|
139
155
|
})
|
|
140
156
|
|
|
157
|
+
suite.add('JSON stringify date', function () {
|
|
158
|
+
JSON.stringify(date)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
suite.add('fast-json-stringify date format', function () {
|
|
162
|
+
stringifyDate(date)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
suite.add('compile-json-stringify date format', function () {
|
|
166
|
+
CJSStringifyDate(date)
|
|
167
|
+
})
|
|
168
|
+
|
|
141
169
|
suite.on('cycle', cycle)
|
|
142
170
|
|
|
143
171
|
suite.run()
|
package/index.js
CHANGED
|
@@ -47,7 +47,12 @@ function mergeLocation (source, dest) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
const arrayItemsReferenceSerializersMap = new Map()
|
|
51
|
+
const objectReferenceSerializersMap = new Map()
|
|
52
|
+
|
|
50
53
|
function build (schema, options) {
|
|
54
|
+
arrayItemsReferenceSerializersMap.clear()
|
|
55
|
+
objectReferenceSerializersMap.clear()
|
|
51
56
|
options = options || {}
|
|
52
57
|
isValidSchema(schema)
|
|
53
58
|
if (options.schema) {
|
|
@@ -144,6 +149,9 @@ function build (schema, options) {
|
|
|
144
149
|
return dependenciesName
|
|
145
150
|
}
|
|
146
151
|
|
|
152
|
+
arrayItemsReferenceSerializersMap.clear()
|
|
153
|
+
objectReferenceSerializersMap.clear()
|
|
154
|
+
|
|
147
155
|
return (Function.apply(null, dependenciesName).apply(null, dependencies))
|
|
148
156
|
}
|
|
149
157
|
|
|
@@ -285,10 +293,7 @@ function $asDatetime (date, skipQuotes) {
|
|
|
285
293
|
function $asDate (date, skipQuotes) {
|
|
286
294
|
const quotes = skipQuotes === true ? '' : '"'
|
|
287
295
|
if (date instanceof Date) {
|
|
288
|
-
|
|
289
|
-
const month = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(date)
|
|
290
|
-
const day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date)
|
|
291
|
-
return quotes + year + '-' + month + '-' + day + quotes
|
|
296
|
+
return quotes + new Date(date.getTime() - (date.getTimezoneOffset() * 60000 )).toISOString().slice(0, 10) + quotes
|
|
292
297
|
} else if (date && typeof date.format === 'function') {
|
|
293
298
|
return quotes + date.format('YYYY-MM-DD') + quotes
|
|
294
299
|
} else {
|
|
@@ -397,51 +402,60 @@ function addPatternProperties (location) {
|
|
|
397
402
|
} catch (err) {
|
|
398
403
|
throw new Error(`${err.message}. Found at ${regex} matching ${JSON.stringify(pp[regex])}`)
|
|
399
404
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
405
|
+
|
|
406
|
+
const ifPpKeyExists = `if (/${regex.replace(/\\*\//g, '\\/')}/.test(keys[i])) {`
|
|
407
|
+
|
|
403
408
|
if (type === 'object') {
|
|
404
409
|
code += `${buildObject(ppLocation, '', 'buildObjectPP' + index)}
|
|
410
|
+
${ifPpKeyExists}
|
|
405
411
|
${addComma}
|
|
406
412
|
json += $asString(keys[i]) + ':' + buildObjectPP${index}(obj[keys[i]])
|
|
407
413
|
`
|
|
408
414
|
} else if (type === 'array') {
|
|
409
415
|
code += `${buildArray(ppLocation, '', 'buildArrayPP' + index)}
|
|
416
|
+
${ifPpKeyExists}
|
|
410
417
|
${addComma}
|
|
411
418
|
json += $asString(keys[i]) + ':' + buildArrayPP${index}(obj[keys[i]])
|
|
412
419
|
`
|
|
413
420
|
} else if (type === 'null') {
|
|
414
421
|
code += `
|
|
422
|
+
${ifPpKeyExists}
|
|
415
423
|
${addComma}
|
|
416
424
|
json += $asString(keys[i]) +':null'
|
|
417
425
|
`
|
|
418
426
|
} else if (type === 'string') {
|
|
419
427
|
code += `
|
|
428
|
+
${ifPpKeyExists}
|
|
420
429
|
${addComma}
|
|
421
430
|
json += $asString(keys[i]) + ':' + ${stringSerializer}(obj[keys[i]])
|
|
422
431
|
`
|
|
423
432
|
} else if (type === 'integer') {
|
|
424
433
|
code += `
|
|
434
|
+
${ifPpKeyExists}
|
|
425
435
|
${addComma}
|
|
426
436
|
json += $asString(keys[i]) + ':' + $asInteger(obj[keys[i]])
|
|
427
437
|
`
|
|
428
438
|
} else if (type === 'number') {
|
|
429
439
|
code += `
|
|
440
|
+
${ifPpKeyExists}
|
|
430
441
|
${addComma}
|
|
431
442
|
json += $asString(keys[i]) + ':' + $asNumber(obj[keys[i]])
|
|
432
443
|
`
|
|
433
444
|
} else if (type === 'boolean') {
|
|
434
445
|
code += `
|
|
446
|
+
${ifPpKeyExists}
|
|
435
447
|
${addComma}
|
|
436
448
|
json += $asString(keys[i]) + ':' + $asBoolean(obj[keys[i]])
|
|
437
449
|
`
|
|
438
450
|
} else if (type === undefined) {
|
|
439
451
|
code += `
|
|
452
|
+
${ifPpKeyExists}
|
|
440
453
|
${addComma}
|
|
441
454
|
json += $asString(keys[i]) + ':' + $asAny(obj[keys[i]])
|
|
442
455
|
`
|
|
443
456
|
} else {
|
|
444
457
|
code += `
|
|
458
|
+
${ifPpKeyExists}
|
|
445
459
|
throw new Error('Cannot coerce ' + obj[keys[i]] + ' to ' + ${JSON.stringify(type)})
|
|
446
460
|
`
|
|
447
461
|
}
|
|
@@ -805,6 +819,12 @@ function buildCode (location, code, laterCode, name) {
|
|
|
805
819
|
`
|
|
806
820
|
}
|
|
807
821
|
|
|
822
|
+
if (schema.allOf) {
|
|
823
|
+
const builtCode = buildCodeWithAllOfs(location, code, laterCode, name)
|
|
824
|
+
code = builtCode.code
|
|
825
|
+
laterCode = builtCode.laterCode
|
|
826
|
+
}
|
|
827
|
+
|
|
808
828
|
return { code: code, laterCode: laterCode }
|
|
809
829
|
}
|
|
810
830
|
|
|
@@ -920,6 +940,16 @@ function buildObject (location, code, name) {
|
|
|
920
940
|
}
|
|
921
941
|
`
|
|
922
942
|
}
|
|
943
|
+
|
|
944
|
+
if (objectReferenceSerializersMap.has(schema)) {
|
|
945
|
+
code += `
|
|
946
|
+
return ${objectReferenceSerializersMap.get(schema)}(input)
|
|
947
|
+
}
|
|
948
|
+
`
|
|
949
|
+
return code
|
|
950
|
+
}
|
|
951
|
+
objectReferenceSerializersMap.set(schema, name)
|
|
952
|
+
|
|
923
953
|
code += `
|
|
924
954
|
var obj = ${toJSON('input')}
|
|
925
955
|
var json = '{'
|
|
@@ -959,9 +989,6 @@ function buildArray (location, code, name, key = null) {
|
|
|
959
989
|
}
|
|
960
990
|
`
|
|
961
991
|
}
|
|
962
|
-
code += `
|
|
963
|
-
var json = '['
|
|
964
|
-
`
|
|
965
992
|
const laterCode = ''
|
|
966
993
|
|
|
967
994
|
// default to any items type
|
|
@@ -975,8 +1002,18 @@ function buildArray (location, code, name, key = null) {
|
|
|
975
1002
|
schema = location.schema
|
|
976
1003
|
schema[fjsCloned] = true
|
|
977
1004
|
}
|
|
1005
|
+
|
|
978
1006
|
location = refFinder(schema.items.$ref, location)
|
|
979
1007
|
schema.items = location.schema
|
|
1008
|
+
|
|
1009
|
+
if (arrayItemsReferenceSerializersMap.has(schema.items)) {
|
|
1010
|
+
code += `
|
|
1011
|
+
return ${arrayItemsReferenceSerializersMap.get(schema.items)}(obj)
|
|
1012
|
+
}
|
|
1013
|
+
`
|
|
1014
|
+
return code
|
|
1015
|
+
}
|
|
1016
|
+
arrayItemsReferenceSerializersMap.set(schema.items, name)
|
|
980
1017
|
}
|
|
981
1018
|
|
|
982
1019
|
let result = { code: '', laterCode: '' }
|
|
@@ -1023,17 +1060,17 @@ function buildArray (location, code, name, key = null) {
|
|
|
1023
1060
|
|
|
1024
1061
|
code += `
|
|
1025
1062
|
var l = obj.length
|
|
1026
|
-
|
|
1063
|
+
var jsonOutput= ''
|
|
1027
1064
|
for (var i = 0; i < l; i++) {
|
|
1028
|
-
var
|
|
1065
|
+
var json = ''
|
|
1066
|
+
${result.code}
|
|
1067
|
+
jsonOutput += json
|
|
1029
1068
|
|
|
1030
|
-
if (
|
|
1031
|
-
|
|
1069
|
+
if (json.length > 0 && i < l - 1) {
|
|
1070
|
+
jsonOutput += ','
|
|
1032
1071
|
}
|
|
1033
|
-
${result.code}
|
|
1034
1072
|
}
|
|
1035
|
-
|
|
1036
|
-
return json
|
|
1073
|
+
return \`[\${jsonOutput}]\`
|
|
1037
1074
|
}
|
|
1038
1075
|
${result.laterCode}
|
|
1039
1076
|
`
|
package/package.json
CHANGED
package/test/allof.test.js
CHANGED
|
@@ -277,6 +277,58 @@ test('object with multiple $refs in allOf', (t) => {
|
|
|
277
277
|
t.equal(value, '{"id1":1,"id2":2}')
|
|
278
278
|
})
|
|
279
279
|
|
|
280
|
+
test('allOf with nested allOf in $ref', (t) => {
|
|
281
|
+
t.plan(1)
|
|
282
|
+
|
|
283
|
+
const schema = {
|
|
284
|
+
title: 'allOf with nested allOf in $ref',
|
|
285
|
+
type: 'object',
|
|
286
|
+
definitions: {
|
|
287
|
+
group: {
|
|
288
|
+
type: 'object',
|
|
289
|
+
allOf: [{
|
|
290
|
+
properties: {
|
|
291
|
+
id2: {
|
|
292
|
+
type: 'integer'
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}, {
|
|
296
|
+
properties: {
|
|
297
|
+
id3: {
|
|
298
|
+
type: 'integer'
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}]
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
allOf: [
|
|
305
|
+
{
|
|
306
|
+
type: 'object',
|
|
307
|
+
properties: {
|
|
308
|
+
id1: {
|
|
309
|
+
type: 'integer'
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
required: [
|
|
313
|
+
'id1'
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
$ref: '#/definitions/group'
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const stringify = build(schema)
|
|
323
|
+
const value = stringify({
|
|
324
|
+
id1: 1,
|
|
325
|
+
id2: 2,
|
|
326
|
+
id3: 3,
|
|
327
|
+
id4: 4 // extra prop shouldn't be in result
|
|
328
|
+
})
|
|
329
|
+
t.equal(value, '{"id1":1,"id2":2,"id3":3}')
|
|
330
|
+
})
|
|
331
|
+
|
|
280
332
|
test('object with external $refs in allOf', (t) => {
|
|
281
333
|
t.plan(1)
|
|
282
334
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tap').test
|
|
4
|
+
const build = require('..')
|
|
5
|
+
|
|
6
|
+
test('can stringify recursive directory tree (issue #181)', (t) => {
|
|
7
|
+
t.plan(1)
|
|
8
|
+
|
|
9
|
+
const schema = {
|
|
10
|
+
definitions: {
|
|
11
|
+
directory: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
name: { type: 'string' },
|
|
15
|
+
subDirectories: {
|
|
16
|
+
type: 'array',
|
|
17
|
+
items: { $ref: '#/definitions/directory' },
|
|
18
|
+
default: []
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
type: 'array',
|
|
24
|
+
items: { $ref: '#/definitions/directory' }
|
|
25
|
+
}
|
|
26
|
+
const stringify = build(schema)
|
|
27
|
+
|
|
28
|
+
t.equal(stringify([
|
|
29
|
+
{ name: 'directory 1', subDirectories: [] },
|
|
30
|
+
{
|
|
31
|
+
name: 'directory 2',
|
|
32
|
+
subDirectories: [
|
|
33
|
+
{ name: 'directory 2.1', subDirectories: [] },
|
|
34
|
+
{ name: 'directory 2.2', subDirectories: [] }
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]), '[{"name":"directory 1","subDirectories":[]},{"name":"directory 2","subDirectories":[{"name":"directory 2.1","subDirectories":[]},{"name":"directory 2.2","subDirectories":[]}]}]')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('can stringify when recursion in external schema', t => {
|
|
41
|
+
t.plan(1)
|
|
42
|
+
|
|
43
|
+
const referenceSchema = {
|
|
44
|
+
$id: 'person',
|
|
45
|
+
type: 'object',
|
|
46
|
+
properties: {
|
|
47
|
+
name: { type: 'string' },
|
|
48
|
+
children: {
|
|
49
|
+
type: 'array',
|
|
50
|
+
items: { $ref: '#' }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const schema = {
|
|
56
|
+
$id: 'mainSchema',
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
people: {
|
|
60
|
+
$ref: 'person'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const stringify = build(schema, {
|
|
65
|
+
schema: {
|
|
66
|
+
[referenceSchema.$id]: referenceSchema
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const value = stringify({ people: { name: 'Elizabeth', children: [{ name: 'Charles' }] } })
|
|
71
|
+
t.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles"}]}}')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('use proper serialize function', t => {
|
|
75
|
+
t.plan(1)
|
|
76
|
+
|
|
77
|
+
const personSchema = {
|
|
78
|
+
$id: 'person',
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
name: { type: 'string' },
|
|
82
|
+
children: {
|
|
83
|
+
type: 'array',
|
|
84
|
+
items: { $ref: '#' }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const directorySchema = {
|
|
90
|
+
$id: 'directory',
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
name: { type: 'string' },
|
|
94
|
+
subDirectories: {
|
|
95
|
+
type: 'array',
|
|
96
|
+
items: { $ref: '#' },
|
|
97
|
+
default: []
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const schema = {
|
|
103
|
+
$id: 'mainSchema',
|
|
104
|
+
type: 'object',
|
|
105
|
+
properties: {
|
|
106
|
+
people: { $ref: 'person' },
|
|
107
|
+
directory: { $ref: 'directory' }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const stringify = build(schema, {
|
|
111
|
+
schema: {
|
|
112
|
+
[personSchema.$id]: personSchema,
|
|
113
|
+
[directorySchema.$id]: directorySchema
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const value = stringify({
|
|
118
|
+
people: {
|
|
119
|
+
name: 'Elizabeth',
|
|
120
|
+
children: [{
|
|
121
|
+
name: 'Charles',
|
|
122
|
+
children: [{ name: 'William', children: [{ name: 'George' }, { name: 'Charlotte' }] }, { name: 'Harry' }]
|
|
123
|
+
}]
|
|
124
|
+
},
|
|
125
|
+
directory: {
|
|
126
|
+
name: 'directory 1',
|
|
127
|
+
subDirectories: [
|
|
128
|
+
{ name: 'directory 1.1', subDirectories: [] },
|
|
129
|
+
{
|
|
130
|
+
name: 'directory 1.2',
|
|
131
|
+
subDirectories: [{ name: 'directory 1.2.1' }, { name: 'directory 1.2.2' }]
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
t.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles","children":[{"name":"William","children":[{"name":"George"},{"name":"Charlotte"}]},{"name":"Harry"}]}]},"directory":{"name":"directory 1","subDirectories":[{"name":"directory 1.1","subDirectories":[]},{"name":"directory 1.2","subDirectories":[{"name":"directory 1.2.1","subDirectories":[]},{"name":"directory 1.2.2","subDirectories":[]}]}]}}')
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('can stringify recursive references in object types (issue #365)', t => {
|
|
140
|
+
t.plan(1)
|
|
141
|
+
|
|
142
|
+
const schema = {
|
|
143
|
+
type: 'object',
|
|
144
|
+
definitions: {
|
|
145
|
+
parentCategory: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
parent: {
|
|
149
|
+
$ref: '#/definitions/parentCategory'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
properties: {
|
|
155
|
+
category: {
|
|
156
|
+
type: 'object',
|
|
157
|
+
properties: {
|
|
158
|
+
parent: {
|
|
159
|
+
$ref: '#/definitions/parentCategory'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const stringify = build(schema)
|
|
167
|
+
const data = {
|
|
168
|
+
category: {
|
|
169
|
+
parent: {
|
|
170
|
+
parent: {
|
|
171
|
+
parent: {
|
|
172
|
+
parent: {}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const value = stringify(data)
|
|
179
|
+
t.equal(value, '{"category":{"parent":{"parent":{"parent":{"parent":{}}}}}}')
|
|
180
|
+
})
|