Skip to content

Commit 310325b

Browse files
refactor: buildArray function (#457)
1 parent 658411c commit 310325b

File tree

2 files changed

+84
-41
lines changed

2 files changed

+84
-41
lines changed

index.js

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -754,45 +754,21 @@ function buildArray (location, locationPath) {
754754
`
755755
}
756756

757-
let result = { code: '' }
758-
const accessor = '[i]'
759-
if (Array.isArray(schema.items)) {
760-
result = schema.items.reduce((res, item, i) => {
761-
const tmpRes = buildValue(locationPath + accessor + i, 'obj[i]', mergeLocation(location, { schema: item }))
762-
const condition = `i === ${i} && ${buildArrayTypeCondition(item.type, accessor)}`
763-
return {
764-
code: `${res.code}
765-
${i > 0 ? 'else' : ''} if (${condition}) {
766-
${tmpRes}
767-
}`
768-
}
769-
}, result)
770-
771-
if (schema.additionalItems) {
772-
const tmpRes = buildValue(locationPath + accessor, 'obj[i]', mergeLocation(location, { schema: schema.items }))
773-
result.code += `
774-
else if (i >= ${schema.items.length}) {
775-
${tmpRes}
776-
}
777-
`
778-
}
779-
780-
result.code += `
781-
else {
782-
throw new Error(\`Item at $\{i} does not match schema definition.\`)
783-
}
784-
`
785-
} else {
786-
result.code = buildValue(locationPath + accessor, 'obj[i]', mergeLocation(location, { schema: schema.items }))
787-
}
788-
789757
functionCode += `
790758
if (!Array.isArray(obj)) {
791759
throw new TypeError(\`The value '$\{obj}' does not match schema definition.\`)
792760
}
761+
const arrayLength = obj.length
793762
`
794763

795-
functionCode += 'const arrayLength = obj.length\n'
764+
if (!schema.additionalItems) {
765+
functionCode += `
766+
if (arrayLength > ${schema.items.length}) {
767+
throw new Error(\`Item at ${schema.items.length} does not match schema definition.\`)
768+
}
769+
`
770+
}
771+
796772
if (largeArrayMechanism !== 'default') {
797773
if (largeArrayMechanism === 'json-stringify') {
798774
functionCode += `if (arrayLength && arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n`
@@ -802,16 +778,54 @@ function buildArray (location, locationPath) {
802778
}
803779

804780
functionCode += `
805-
let jsonOutput= ''
806-
for (let i = 0; i < arrayLength; i++) {
807-
let json = ''
808-
${result.code}
809-
jsonOutput += json
781+
let jsonOutput = ''
782+
`
810783

811-
if (json.length > 0 && i < arrayLength - 1) {
812-
jsonOutput += ','
813-
}
784+
const accessor = '[i]'
785+
if (Array.isArray(schema.items)) {
786+
for (let i = 0; i < schema.items.length; i++) {
787+
const item = schema.items[i]
788+
const tmpRes = buildValue(locationPath + accessor + i, `obj[${i}]`, mergeLocation(location, { schema: item }))
789+
functionCode += `
790+
if (${i} < arrayLength) {
791+
if (${buildArrayTypeCondition(item.type, `[${i}]`)}) {
792+
let json = ''
793+
${tmpRes}
794+
jsonOutput += json
795+
if (${i} < arrayLength - 1) {
796+
jsonOutput += ','
797+
}
798+
} else {
799+
throw new Error(\`Item at ${i} does not match schema definition.\`)
800+
}
801+
}
802+
`
803+
}
804+
805+
if (schema.additionalItems) {
806+
functionCode += `
807+
for (let i = ${schema.items.length}; i < arrayLength; i++) {
808+
let json = JSON.stringify(obj[i])
809+
jsonOutput += json
810+
if (i < arrayLength - 1) {
811+
jsonOutput += ','
812+
}
813+
}`
814814
}
815+
} else {
816+
const code = buildValue(locationPath + accessor, 'obj[i]', mergeLocation(location, { schema: schema.items }))
817+
functionCode += `
818+
for (let i = 0; i < arrayLength; i++) {
819+
let json = ''
820+
${code}
821+
jsonOutput += json
822+
if (i < arrayLength - 1) {
823+
jsonOutput += ','
824+
}
825+
}`
826+
}
827+
828+
functionCode += `
815829
return \`[\${jsonOutput}]\`
816830
}`
817831

test/array.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,35 @@ test('array items is a list of schema and additionalItems is true, just the desc
218218
t.equal(result, '{"foo":["foo","bar",1]}')
219219
})
220220

221+
test('array items is a list of schema and additionalItems is true, just the described item is validated', (t) => {
222+
t.plan(1)
223+
224+
const schema = {
225+
type: 'object',
226+
properties: {
227+
foo: {
228+
type: 'array',
229+
items: [
230+
{
231+
type: 'string'
232+
},
233+
{
234+
type: 'number'
235+
}
236+
],
237+
additionalItems: true
238+
}
239+
}
240+
}
241+
242+
const stringify = build(schema)
243+
const result = stringify({
244+
foo: ['foo']
245+
})
246+
247+
t.equal(result, '{"foo":["foo"]}')
248+
})
249+
221250
test('array items is a list of schema and additionalItems is false', (t) => {
222251
t.plan(1)
223252

0 commit comments

Comments
 (0)