fast-json-stringify 3.1.0 → 4.1.0
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/workflows/benchmark.yml +3 -3
- package/.github/workflows/ci.yml +3 -33
- package/README.md +37 -13
- package/ajv.js +37 -0
- package/benchmark/bench-cmp-branch.js +114 -0
- package/{bench.js → benchmark/bench-cmp-lib.js} +4 -4
- package/benchmark/bench-thread.js +21 -0
- package/benchmark/bench.js +251 -0
- package/example.js +0 -3
- package/index.d.ts +4 -0
- package/index.js +402 -691
- package/package.json +11 -5
- package/serializer.js +168 -0
- package/test/additionalProperties.test.js +23 -19
- package/test/allof.test.js +56 -0
- package/test/anyof.test.js +88 -9
- package/test/array.test.js +110 -23
- package/test/basic.test.js +8 -8
- package/test/date.test.js +62 -35
- package/test/debug-mode.test.js +1 -1
- package/test/fixtures/.keep +0 -0
- package/test/if-then-else.test.js +2 -2
- package/test/nestedObjects.test.js +31 -0
- package/test/nullable.test.js +343 -15
- package/test/oneof.test.js +9 -22
- package/test/patternProperties.test.js +17 -6
- package/test/recursion.test.js +65 -0
- package/test/required.test.js +1 -1
- package/test/sanitize3.test.js +9 -11
- package/test/standalone-mode.test.js +38 -0
- package/test/typesArray.test.js +40 -3
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Stringify your JSON at max speed",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
8
|
+
"bench": "node ./benchmark/bench.js",
|
|
9
|
+
"bench:cmp": "node ./benchmark/bench-cmp-branch.js",
|
|
10
|
+
"bench:cmp:ci": "node ./benchmark/bench-cmp-branch.js --ci",
|
|
11
|
+
"benchmark": "node ./benchmark/bench-cmp-lib.js",
|
|
9
12
|
"lint:fix": "standard --fix",
|
|
10
13
|
"test:lint": "standard",
|
|
11
14
|
"test:typescript": "tsc --project ./test/types/tsconfig.json",
|
|
@@ -32,13 +35,16 @@
|
|
|
32
35
|
"devDependencies": {
|
|
33
36
|
"@sinclair/typebox": "^0.23.3",
|
|
34
37
|
"benchmark": "^2.1.4",
|
|
38
|
+
"chalk": "^4.1.2",
|
|
35
39
|
"compile-json-stringify": "^0.1.2",
|
|
40
|
+
"inquirer": "^8.2.4",
|
|
36
41
|
"is-my-json-valid": "^2.20.0",
|
|
37
|
-
"
|
|
42
|
+
"luxon": "^2.4.0",
|
|
38
43
|
"pre-commit": "^1.2.2",
|
|
39
44
|
"proxyquire": "^2.1.3",
|
|
40
45
|
"semver": "^7.1.0",
|
|
41
|
-
"
|
|
46
|
+
"simple-git": "^3.7.1",
|
|
47
|
+
"standard": "^17.0.0",
|
|
42
48
|
"tap": "^16.0.1",
|
|
43
49
|
"typescript": "^4.0.2",
|
|
44
50
|
"webpack": "^5.40.0"
|
|
@@ -47,7 +53,7 @@
|
|
|
47
53
|
"ajv": "^8.10.0",
|
|
48
54
|
"ajv-formats": "^2.1.1",
|
|
49
55
|
"deepmerge": "^4.2.2",
|
|
50
|
-
"fast-uri": "^
|
|
56
|
+
"fast-uri": "^2.0.0",
|
|
51
57
|
"rfdc": "^1.2.0",
|
|
52
58
|
"string-similarity": "^4.0.1"
|
|
53
59
|
},
|
package/serializer.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = class Serializer {
|
|
4
|
+
constructor (options = {}) {
|
|
5
|
+
switch (options.rounding) {
|
|
6
|
+
case 'floor':
|
|
7
|
+
this.parseInteger = Math.floor
|
|
8
|
+
break
|
|
9
|
+
case 'ceil':
|
|
10
|
+
this.parseInteger = Math.ceil
|
|
11
|
+
break
|
|
12
|
+
case 'round':
|
|
13
|
+
this.parseInteger = Math.round
|
|
14
|
+
break
|
|
15
|
+
default:
|
|
16
|
+
this.parseInteger = Math.trunc
|
|
17
|
+
break
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
asAny (i) {
|
|
22
|
+
return JSON.stringify(i)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
asNull () {
|
|
26
|
+
return 'null'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
asInteger (i) {
|
|
30
|
+
if (typeof i === 'bigint') {
|
|
31
|
+
return i.toString()
|
|
32
|
+
} else if (Number.isInteger(i)) {
|
|
33
|
+
return '' + i
|
|
34
|
+
} else {
|
|
35
|
+
/* eslint no-undef: "off" */
|
|
36
|
+
const integer = this.parseInteger(i)
|
|
37
|
+
if (Number.isNaN(integer)) {
|
|
38
|
+
throw new Error(`The value "${i}" cannot be converted to an integer.`)
|
|
39
|
+
} else {
|
|
40
|
+
return '' + integer
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
asIntegerNullable (i) {
|
|
46
|
+
return i === null ? 'null' : this.asInteger(i)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
asNumber (i) {
|
|
50
|
+
const num = Number(i)
|
|
51
|
+
if (Number.isNaN(num)) {
|
|
52
|
+
throw new Error(`The value "${i}" cannot be converted to a number.`)
|
|
53
|
+
} else {
|
|
54
|
+
return '' + num
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
asNumberNullable (i) {
|
|
59
|
+
return i === null ? 'null' : this.asNumber(i)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
asBoolean (bool) {
|
|
63
|
+
return bool && 'true' || 'false' // eslint-disable-line
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
asBooleanNullable (bool) {
|
|
67
|
+
return bool === null ? 'null' : this.asBoolean(bool)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
asDatetime (date, skipQuotes) {
|
|
71
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
72
|
+
if (date instanceof Date) {
|
|
73
|
+
return quotes + date.toISOString() + quotes
|
|
74
|
+
}
|
|
75
|
+
return this.asString(date, skipQuotes)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
asDatetimeNullable (date, skipQuotes) {
|
|
79
|
+
return date === null ? 'null' : this.asDatetime(date, skipQuotes)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
asDate (date, skipQuotes) {
|
|
83
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
84
|
+
if (date instanceof Date) {
|
|
85
|
+
return quotes + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) + quotes
|
|
86
|
+
}
|
|
87
|
+
return this.asString(date, skipQuotes)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
asDateNullable (date, skipQuotes) {
|
|
91
|
+
return date === null ? 'null' : this.asDate(date, skipQuotes)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
asTime (date, skipQuotes) {
|
|
95
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
96
|
+
if (date instanceof Date) {
|
|
97
|
+
return quotes + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(11, 19) + quotes
|
|
98
|
+
}
|
|
99
|
+
return this.asString(date, skipQuotes)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
asTimeNullable (date, skipQuotes) {
|
|
103
|
+
return date === null ? 'null' : this.asTime(date, skipQuotes)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
asString (str, skipQuotes) {
|
|
107
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
108
|
+
if (str instanceof Date) {
|
|
109
|
+
return quotes + str.toISOString() + quotes
|
|
110
|
+
} else if (str === null) {
|
|
111
|
+
return quotes + quotes
|
|
112
|
+
} else if (str instanceof RegExp) {
|
|
113
|
+
str = str.source
|
|
114
|
+
} else if (typeof str !== 'string') {
|
|
115
|
+
str = str.toString()
|
|
116
|
+
}
|
|
117
|
+
// If we skipQuotes it means that we are using it as test
|
|
118
|
+
// no need to test the string length for the render
|
|
119
|
+
if (skipQuotes) {
|
|
120
|
+
return str
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (str.length < 42) {
|
|
124
|
+
return this.asStringSmall(str)
|
|
125
|
+
} else {
|
|
126
|
+
return JSON.stringify(str)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
asStringNullable (str) {
|
|
131
|
+
return str === null ? 'null' : this.asString(str)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// magically escape strings for json
|
|
135
|
+
// relying on their charCodeAt
|
|
136
|
+
// everything below 32 needs JSON.stringify()
|
|
137
|
+
// every string that contain surrogate needs JSON.stringify()
|
|
138
|
+
// 34 and 92 happens all the time, so we
|
|
139
|
+
// have a fast case for them
|
|
140
|
+
asStringSmall (str) {
|
|
141
|
+
const l = str.length
|
|
142
|
+
let result = ''
|
|
143
|
+
let last = 0
|
|
144
|
+
let found = false
|
|
145
|
+
let surrogateFound = false
|
|
146
|
+
let point = 255
|
|
147
|
+
// eslint-disable-next-line
|
|
148
|
+
for (var i = 0; i < l && point >= 32; i++) {
|
|
149
|
+
point = str.charCodeAt(i)
|
|
150
|
+
if (point >= 0xD800 && point <= 0xDFFF) {
|
|
151
|
+
// The current character is a surrogate.
|
|
152
|
+
surrogateFound = true
|
|
153
|
+
}
|
|
154
|
+
if (point === 34 || point === 92) {
|
|
155
|
+
result += str.slice(last, i) + '\\'
|
|
156
|
+
last = i
|
|
157
|
+
found = true
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!found) {
|
|
162
|
+
result = str
|
|
163
|
+
} else {
|
|
164
|
+
result += str.slice(last)
|
|
165
|
+
}
|
|
166
|
+
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -19,7 +19,7 @@ test('additionalProperties', (t) => {
|
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
const obj = { str: 'test', foo: 42, ofoo: true, foof: 'string', objfoo: { a: true } }
|
|
22
|
-
t.equal('{"str":"test","foo":"42","ofoo":"true","foof":"string","objfoo":"[object Object]"}'
|
|
22
|
+
t.equal(stringify(obj), '{"str":"test","foo":"42","ofoo":"true","foof":"string","objfoo":"[object Object]"}')
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
test('additionalProperties should not change properties', (t) => {
|
|
@@ -38,7 +38,7 @@ test('additionalProperties should not change properties', (t) => {
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
const obj = { foo: '42', ofoo: 42 }
|
|
41
|
-
t.equal('{"foo":"42","ofoo":42}'
|
|
41
|
+
t.equal(stringify(obj), '{"foo":"42","ofoo":42}')
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
test('additionalProperties should not change properties and patternProperties', (t) => {
|
|
@@ -62,7 +62,7 @@ test('additionalProperties should not change properties and patternProperties',
|
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
const obj = { foo: '42', ofoo: 42, test: '42' }
|
|
65
|
-
t.equal('{"foo":"42","ofoo":"42","test":42}'
|
|
65
|
+
t.equal(stringify(obj), '{"foo":"42","ofoo":"42","test":42}')
|
|
66
66
|
})
|
|
67
67
|
|
|
68
68
|
test('additionalProperties set to true, use of fast-safe-stringify', (t) => {
|
|
@@ -75,7 +75,7 @@ test('additionalProperties set to true, use of fast-safe-stringify', (t) => {
|
|
|
75
75
|
})
|
|
76
76
|
|
|
77
77
|
const obj = { foo: true, ofoo: 42, arrfoo: ['array', 'test'], objfoo: { a: 'world' } }
|
|
78
|
-
t.equal('{"foo":true,"ofoo":42,"arrfoo":["array","test"],"objfoo":{"a":"world"}}'
|
|
78
|
+
t.equal(stringify(obj), '{"foo":true,"ofoo":42,"arrfoo":["array","test"],"objfoo":{"a":"world"}}')
|
|
79
79
|
})
|
|
80
80
|
|
|
81
81
|
test('additionalProperties - string coerce', (t) => {
|
|
@@ -90,7 +90,7 @@ test('additionalProperties - string coerce', (t) => {
|
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
const obj = { foo: true, ofoo: 42, arrfoo: ['array', 'test'], objfoo: { a: 'world' } }
|
|
93
|
-
t.equal('{"foo":"true","ofoo":"42","arrfoo":"array,test","objfoo":"[object Object]"}'
|
|
93
|
+
t.equal(stringify(obj), '{"foo":"true","ofoo":"42","arrfoo":"array,test","objfoo":"[object Object]"}')
|
|
94
94
|
})
|
|
95
95
|
|
|
96
96
|
test('additionalProperties - number skip', (t) => {
|
|
@@ -104,7 +104,8 @@ test('additionalProperties - number skip', (t) => {
|
|
|
104
104
|
}
|
|
105
105
|
})
|
|
106
106
|
|
|
107
|
-
const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
|
|
107
|
+
// const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
|
|
108
|
+
const obj = { foo: true, ofoo: '42' }
|
|
108
109
|
t.equal(stringify(obj), '{"foo":1,"ofoo":42}')
|
|
109
110
|
})
|
|
110
111
|
|
|
@@ -140,11 +141,11 @@ test('additionalProperties - object coerce', (t) => {
|
|
|
140
141
|
})
|
|
141
142
|
|
|
142
143
|
const obj = { objfoo: { answer: 42 } }
|
|
143
|
-
t.equal('{"objfoo":{"answer":42}}'
|
|
144
|
+
t.equal(stringify(obj), '{"objfoo":{"answer":42}}')
|
|
144
145
|
})
|
|
145
146
|
|
|
146
147
|
test('additionalProperties - array coerce', (t) => {
|
|
147
|
-
t.plan(
|
|
148
|
+
t.plan(2)
|
|
148
149
|
const stringify = build({
|
|
149
150
|
title: 'check array coerce',
|
|
150
151
|
type: 'object',
|
|
@@ -157,8 +158,11 @@ test('additionalProperties - array coerce', (t) => {
|
|
|
157
158
|
}
|
|
158
159
|
})
|
|
159
160
|
|
|
160
|
-
const
|
|
161
|
-
t.equal('{"
|
|
161
|
+
const coercibleValues = { arrfoo: [1, 2] }
|
|
162
|
+
t.equal(stringify(coercibleValues), '{"arrfoo":["1","2"]}')
|
|
163
|
+
|
|
164
|
+
const incoercibleValues = { foo: 'true', ofoo: 0, objfoo: { tyrion: 'lannister' } }
|
|
165
|
+
t.throws(() => stringify(incoercibleValues))
|
|
162
166
|
})
|
|
163
167
|
|
|
164
168
|
test('additionalProperties with empty schema', (t) => {
|
|
@@ -169,7 +173,7 @@ test('additionalProperties with empty schema', (t) => {
|
|
|
169
173
|
})
|
|
170
174
|
|
|
171
175
|
const obj = { a: 1, b: true, c: null }
|
|
172
|
-
t.equal('{"a":1,"b":true,"c":null}'
|
|
176
|
+
t.equal(stringify(obj), '{"a":1,"b":true,"c":null}')
|
|
173
177
|
})
|
|
174
178
|
|
|
175
179
|
test('additionalProperties with nested empty schema', (t) => {
|
|
@@ -183,7 +187,7 @@ test('additionalProperties with nested empty schema', (t) => {
|
|
|
183
187
|
})
|
|
184
188
|
|
|
185
189
|
const obj = { data: { a: 1, b: true, c: null } }
|
|
186
|
-
t.equal('{"data":{"a":1,"b":true,"c":null}}'
|
|
190
|
+
t.equal(stringify(obj), '{"data":{"a":1,"b":true,"c":null}}')
|
|
187
191
|
})
|
|
188
192
|
|
|
189
193
|
test('nested additionalProperties', (t) => {
|
|
@@ -203,7 +207,7 @@ test('nested additionalProperties', (t) => {
|
|
|
203
207
|
})
|
|
204
208
|
|
|
205
209
|
const obj = [{ ap: { value: 'string' } }]
|
|
206
|
-
t.equal('[{"ap":{"value":"string"}}]'
|
|
210
|
+
t.equal(stringify(obj), '[{"ap":{"value":"string"}}]')
|
|
207
211
|
})
|
|
208
212
|
|
|
209
213
|
test('very nested additionalProperties', (t) => {
|
|
@@ -240,7 +244,7 @@ test('very nested additionalProperties', (t) => {
|
|
|
240
244
|
})
|
|
241
245
|
|
|
242
246
|
const obj = [{ ap: { nested: { moarNested: { finally: { value: 'str' } } } } }]
|
|
243
|
-
t.equal('[{"ap":{"nested":{"moarNested":{"finally":{"value":"str"}}}}}]'
|
|
247
|
+
t.equal(stringify(obj), '[{"ap":{"nested":{"moarNested":{"finally":{"value":"str"}}}}}]')
|
|
244
248
|
})
|
|
245
249
|
|
|
246
250
|
test('nested additionalProperties set to true', (t) => {
|
|
@@ -257,7 +261,7 @@ test('nested additionalProperties set to true', (t) => {
|
|
|
257
261
|
})
|
|
258
262
|
|
|
259
263
|
const obj = { ap: { value: 'string', someNumber: 42 } }
|
|
260
|
-
t.equal('{"ap":{"value":"string","someNumber":42}}'
|
|
264
|
+
t.equal(stringify(obj), '{"ap":{"value":"string","someNumber":42}}')
|
|
261
265
|
})
|
|
262
266
|
|
|
263
267
|
test('field passed to fastSafeStringify as undefined should be removed', (t) => {
|
|
@@ -274,7 +278,7 @@ test('field passed to fastSafeStringify as undefined should be removed', (t) =>
|
|
|
274
278
|
})
|
|
275
279
|
|
|
276
280
|
const obj = { ap: { value: 'string', someNumber: undefined } }
|
|
277
|
-
t.equal('{"ap":{"value":"string"}}'
|
|
281
|
+
t.equal(stringify(obj), '{"ap":{"value":"string"}}')
|
|
278
282
|
})
|
|
279
283
|
|
|
280
284
|
test('property without type but with enum, will acts as additionalProperties', (t) => {
|
|
@@ -290,7 +294,7 @@ test('property without type but with enum, will acts as additionalProperties', (
|
|
|
290
294
|
})
|
|
291
295
|
|
|
292
296
|
const obj = { ap: { additional: 'field' } }
|
|
293
|
-
t.equal('{"ap":{"additional":"field"}}'
|
|
297
|
+
t.equal(stringify(obj), '{"ap":{"additional":"field"}}')
|
|
294
298
|
})
|
|
295
299
|
|
|
296
300
|
test('property without type but with enum, will acts as additionalProperties without overwriting', (t) => {
|
|
@@ -307,7 +311,7 @@ test('property without type but with enum, will acts as additionalProperties wit
|
|
|
307
311
|
})
|
|
308
312
|
|
|
309
313
|
const obj = { ap: { additional: 'field' } }
|
|
310
|
-
t.equal('{"ap":{}}'
|
|
314
|
+
t.equal(stringify(obj), '{"ap":{}}')
|
|
311
315
|
})
|
|
312
316
|
|
|
313
317
|
test('function and symbol references are not serialized as undefined', (t) => {
|
|
@@ -324,5 +328,5 @@ test('function and symbol references are not serialized as undefined', (t) => {
|
|
|
324
328
|
})
|
|
325
329
|
|
|
326
330
|
const obj = { str: 'x', test: 'test', meth: () => 'x', sym: Symbol('x') }
|
|
327
|
-
t.equal('{"str":"x","test":"test"}'
|
|
331
|
+
t.equal(stringify(obj), '{"str":"x","test":"test"}')
|
|
328
332
|
})
|
package/test/allof.test.js
CHANGED
|
@@ -1,8 +1,64 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const test = require('tap').test
|
|
4
|
+
const { DateTime } = require('luxon')
|
|
4
5
|
const build = require('..')
|
|
5
6
|
|
|
7
|
+
test('allOf: combine type and format ', (t) => {
|
|
8
|
+
t.plan(1)
|
|
9
|
+
|
|
10
|
+
const schema = {
|
|
11
|
+
allOf: [
|
|
12
|
+
{ type: 'string' },
|
|
13
|
+
{ format: 'time' }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
const stringify = build(schema)
|
|
17
|
+
const date = new Date()
|
|
18
|
+
const value = stringify(date)
|
|
19
|
+
t.equal(value, `"${DateTime.fromJSDate(date).toFormat('HH:mm:ss')}"`)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('allOf: combine additional properties ', (t) => {
|
|
23
|
+
t.plan(1)
|
|
24
|
+
|
|
25
|
+
const schema = {
|
|
26
|
+
allOf: [
|
|
27
|
+
{ type: 'object' },
|
|
28
|
+
{
|
|
29
|
+
type: 'object',
|
|
30
|
+
additionalProperties: { type: 'boolean' }
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
const stringify = build(schema)
|
|
35
|
+
const data = { property: true }
|
|
36
|
+
const value = stringify(data)
|
|
37
|
+
t.equal(value, JSON.stringify(data))
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('allOf: combine pattern properties', (t) => {
|
|
41
|
+
t.plan(1)
|
|
42
|
+
|
|
43
|
+
const schema = {
|
|
44
|
+
allOf: [
|
|
45
|
+
{ type: 'object' },
|
|
46
|
+
{
|
|
47
|
+
type: 'object',
|
|
48
|
+
patternProperties: {
|
|
49
|
+
foo: {
|
|
50
|
+
type: 'number'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
const stringify = build(schema)
|
|
57
|
+
const data = { foo: 42 }
|
|
58
|
+
const value = stringify(data)
|
|
59
|
+
t.equal(value, JSON.stringify(data))
|
|
60
|
+
})
|
|
61
|
+
|
|
6
62
|
test('object with allOf and multiple schema on the allOf', (t) => {
|
|
7
63
|
t.plan(4)
|
|
8
64
|
|
package/test/anyof.test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { DateTime } = require('luxon')
|
|
3
4
|
const { test } = require('tap')
|
|
4
5
|
const build = require('..')
|
|
5
6
|
|
|
@@ -113,11 +114,7 @@ test('object with field of type string and coercion disable ', (t) => {
|
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
const stringify = build(schema)
|
|
116
|
-
|
|
117
|
-
const value = stringify({
|
|
118
|
-
str: 1
|
|
119
|
-
})
|
|
120
|
-
t.equal(value, '{"str":null}')
|
|
117
|
+
t.throws(() => stringify({ str: 1 }))
|
|
121
118
|
})
|
|
122
119
|
|
|
123
120
|
test('object with field of type string and coercion enable ', (t) => {
|
|
@@ -224,7 +221,7 @@ test('symbol value in schema', (t) => {
|
|
|
224
221
|
t.equal(stringify({ value: 'foo' }), '{"value":"foo"}')
|
|
225
222
|
t.equal(stringify({ value: 'bar' }), '{"value":"bar"}')
|
|
226
223
|
t.equal(stringify({ value: 'baz' }), '{"value":"baz"}')
|
|
227
|
-
t.
|
|
224
|
+
t.throws(() => stringify({ value: 'qux' }))
|
|
228
225
|
})
|
|
229
226
|
|
|
230
227
|
test('anyOf and $ref together', (t) => {
|
|
@@ -472,6 +469,90 @@ test('anyOf object with field date-time of type string with format or null', (t)
|
|
|
472
469
|
}), `{"prop":"${toStringify.toISOString()}"}`)
|
|
473
470
|
})
|
|
474
471
|
|
|
472
|
+
test('anyOf object with nested field date-time of type string with format or null', (t) => {
|
|
473
|
+
t.plan(1)
|
|
474
|
+
const withOneOfSchema = {
|
|
475
|
+
type: 'object',
|
|
476
|
+
properties: {
|
|
477
|
+
prop: {
|
|
478
|
+
anyOf: [{
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {
|
|
481
|
+
nestedProp: {
|
|
482
|
+
type: 'string',
|
|
483
|
+
format: 'date-time'
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}]
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const withOneOfStringify = build(withOneOfSchema)
|
|
492
|
+
|
|
493
|
+
const data = {
|
|
494
|
+
prop: { nestedProp: new Date() }
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
t.equal(withOneOfStringify(data), JSON.stringify(data))
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
test('anyOf object with nested field date of type string with format or null', (t) => {
|
|
501
|
+
t.plan(1)
|
|
502
|
+
const withOneOfSchema = {
|
|
503
|
+
type: 'object',
|
|
504
|
+
properties: {
|
|
505
|
+
prop: {
|
|
506
|
+
anyOf: [{
|
|
507
|
+
type: 'object',
|
|
508
|
+
properties: {
|
|
509
|
+
nestedProp: {
|
|
510
|
+
type: 'string',
|
|
511
|
+
format: 'date'
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}]
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const withOneOfStringify = build(withOneOfSchema)
|
|
520
|
+
|
|
521
|
+
const data = {
|
|
522
|
+
prop: { nestedProp: new Date() }
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
t.equal(withOneOfStringify(data), `{"prop":{"nestedProp":"${DateTime.fromJSDate(data.prop.nestedProp).toISODate()}"}}`)
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
test('anyOf object with nested field time of type string with format or null', (t) => {
|
|
529
|
+
t.plan(1)
|
|
530
|
+
const withOneOfSchema = {
|
|
531
|
+
type: 'object',
|
|
532
|
+
properties: {
|
|
533
|
+
prop: {
|
|
534
|
+
anyOf: [{
|
|
535
|
+
type: 'object',
|
|
536
|
+
properties: {
|
|
537
|
+
nestedProp: {
|
|
538
|
+
type: 'string',
|
|
539
|
+
format: 'time'
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}]
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const withOneOfStringify = build(withOneOfSchema)
|
|
548
|
+
|
|
549
|
+
const data = {
|
|
550
|
+
prop: { nestedProp: new Date() }
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
t.equal(withOneOfStringify(data), `{"prop":{"nestedProp":"${DateTime.fromJSDate(data.prop.nestedProp).toFormat('HH:mm:ss')}"}}`)
|
|
554
|
+
})
|
|
555
|
+
|
|
475
556
|
test('anyOf object with field date of type string with format or null', (t) => {
|
|
476
557
|
t.plan(1)
|
|
477
558
|
const toStringify = '2011-01-01'
|
|
@@ -513,7 +594,5 @@ test('anyOf object with invalid field date of type string with format or null',
|
|
|
513
594
|
}
|
|
514
595
|
|
|
515
596
|
const withOneOfStringify = build(withOneOfSchema)
|
|
516
|
-
t.
|
|
517
|
-
prop: toStringify
|
|
518
|
-
}), '{"prop":null}')
|
|
597
|
+
t.throws(() => withOneOfStringify({ prop: toStringify }))
|
|
519
598
|
})
|