Skip to content

Commit 4aaaff6

Browse files
ruiaraujomcollina
authored andcommitted
Fix object and null possible type handling. (#104)
* Fix object and null possible type handling. Remove ajv for multiple type handling. * Remove object spreading.
1 parent 0b12eb5 commit 4aaaff6

File tree

3 files changed

+65
-52
lines changed

3 files changed

+65
-52
lines changed

bench.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const schema = {
1111
'type': 'string'
1212
},
1313
'lastName': {
14-
'type': 'string'
14+
'type': ['string', 'null']
1515
},
1616
'age': {
1717
'description': 'Age in years',

index.js

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ function build (schema, options) {
9494

9595
var dependencies = []
9696
var dependenciesName = []
97-
if (hasAnyOf(schema) || hasArrayOfTypes(schema) || hasShemaSomeIf) {
97+
if (hasAnyOf(schema) || hasShemaSomeIf) {
9898
dependencies.push(new Ajv())
9999
dependenciesName.push('ajv')
100100
}
@@ -117,40 +117,6 @@ function hasAnyOf (schema) {
117117
return false
118118
}
119119

120-
function hasArrayOfTypes (schema) {
121-
if (Array.isArray(schema.type)) { return true }
122-
var i
123-
124-
if (schema.type === 'object') {
125-
if (schema.properties) {
126-
var propertyKeys = Object.keys(schema.properties)
127-
for (i = 0; i < propertyKeys.length; i++) {
128-
if (hasArrayOfTypes(schema.properties[propertyKeys[i]])) {
129-
return true
130-
}
131-
}
132-
}
133-
} else if (schema.type === 'array') {
134-
if (Array.isArray(schema.items)) {
135-
for (i = 0; i < schema.items.length; i++) {
136-
if (hasArrayOfTypes(schema.items[i])) {
137-
return true
138-
}
139-
}
140-
} else if (schema.items) {
141-
return hasArrayOfTypes(schema.items)
142-
}
143-
} else if (Array.isArray(schema.anyOf)) {
144-
for (i = 0; i < schema.anyOf.length; i++) {
145-
if (hasArrayOfTypes(schema.anyOf[i])) {
146-
return true
147-
}
148-
}
149-
}
150-
151-
return false
152-
}
153-
154120
function hasIf (schema) {
155121
const str = JSON.stringify(schema)
156122
return /"if":{/.test(str) && /"then":{/.test(str)
@@ -764,17 +730,29 @@ function nested (laterCode, name, key, schema, externalSchema, fullSchema, subKe
764730
break
765731
default:
766732
if (Array.isArray(type)) {
767-
type.forEach((type, index) => {
768-
var tempSchema = {type: type}
733+
const nullIndex = type.indexOf('null')
734+
const sortedTypes = nullIndex !== -1 ? [type[nullIndex]].concat(type.slice(0, nullIndex)).concat(type.slice(nullIndex + 1)) : type
735+
sortedTypes.forEach((type, index) => {
736+
var tempSchema = Object.assign({}, schema, {type})
769737
var nestedResult = nested(laterCode, name, key, tempSchema, externalSchema, fullSchema, subKey)
770738
if (type === 'string') {
771739
code += `
772-
${index === 0 ? 'if' : 'else if'}(obj${accessor} instanceof Date || ajv.validate(${require('util').inspect(tempSchema, {depth: null})}, obj${accessor}))
740+
${index === 0 ? 'if' : 'else if'}(typeof obj${accessor} === "${type}" || obj${accessor} instanceof Date || obj${accessor} instanceof RegExp)
773741
${nestedResult.code}
774742
`
743+
} else if (type === 'null') {
744+
code += `
745+
${index === 0 ? 'if' : 'else if'}(obj${accessor} == null)
746+
${nestedResult.code}
747+
`
748+
} else if (type === 'array') {
749+
code += `
750+
${index === 0 ? 'if' : 'else if'}(Array.isArray(obj${accessor}))
751+
${nestedResult.code}
752+
`
775753
} else {
776754
code += `
777-
${index === 0 ? 'if' : 'else if'}(ajv.validate(${require('util').inspect(tempSchema, {depth: null})}, obj${accessor}))
755+
${index === 0 ? 'if' : 'else if'}(typeof obj${accessor} === "${type}")
778756
${nestedResult.code}
779757
`
780758
}

test/typesArray.test.js

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,83 @@
33
const test = require('tap').test
44
const build = require('..')
55

6-
test('simple object with multi-type property', (t) => {
7-
t.plan(2)
6+
test('possibly null object with multi-type property', (t) => {
7+
t.plan(3)
88

99
const schema = {
1010
title: 'simple object with multi-type property',
1111
type: 'object',
1212
properties: {
13-
stringOrNumber: {
14-
type: ['string', 'number']
13+
objectOrNull: {
14+
type: ['object', 'null'],
15+
properties: {
16+
stringOrNumber: {
17+
type: ['string', 'number']
18+
}
19+
}
1520
}
1621
}
1722
}
1823
const stringify = build(schema)
1924

2025
try {
2126
const value = stringify({
22-
stringOrNumber: 'string'
27+
objectOrNull: {
28+
stringOrNumber: 'string'
29+
}
2330
})
24-
t.is(value, '{"stringOrNumber":"string"}')
31+
t.is(value, '{"objectOrNull":{"stringOrNumber":"string"}}')
2532
} catch (e) {
2633
t.fail()
2734
}
2835

2936
try {
3037
const value = stringify({
31-
stringOrNumber: 42
38+
objectOrNull: {
39+
stringOrNumber: 42
40+
}
3241
})
33-
t.is(value, '{"stringOrNumber":42}')
42+
t.is(value, '{"objectOrNull":{"stringOrNumber":42}}')
43+
} catch (e) {
44+
t.fail()
45+
}
46+
try {
47+
const value = stringify({
48+
objectOrNull: null
49+
})
50+
t.is(value, '{"objectOrNull":null}')
3451
} catch (e) {
3552
t.fail()
3653
}
3754
})
3855

39-
test('object with array of multiple types', (t) => {
40-
t.plan(3)
56+
test('object with possibly null array of multiple types', (t) => {
57+
t.plan(5)
4158

4259
const schema = {
4360
title: 'object with array of multiple types',
4461
type: 'object',
4562
properties: {
4663
arrayOfStringsAndNumbers: {
47-
type: 'array',
64+
type: ['array', 'null'],
4865
items: {
49-
type: ['string', 'number']
66+
type: ['string', 'number', 'null']
5067
}
5168
}
5269
}
5370
}
5471
const stringify = build(schema)
5572

73+
try {
74+
const value = stringify({
75+
arrayOfStringsAndNumbers: null
76+
})
77+
t.is(value, '{"arrayOfStringsAndNumbers":null}')
78+
} catch (e) {
79+
console.log(e)
80+
t.fail()
81+
}
82+
5683
try {
5784
const value = stringify({
5885
arrayOfStringsAndNumbers: ['string1', 'string2']
@@ -80,6 +107,14 @@ test('object with array of multiple types', (t) => {
80107
} catch (e) {
81108
t.fail()
82109
}
110+
try {
111+
const value = stringify({
112+
arrayOfStringsAndNumbers: ['string1', null, 42, 7, 'string2', null]
113+
})
114+
t.is(value, '{"arrayOfStringsAndNumbers":["string1",null,42,7,"string2",null]}')
115+
} catch (e) {
116+
t.fail()
117+
}
83118
})
84119

85120
test('object with tuple of multiple types', (t) => {

0 commit comments

Comments
 (0)