Skip to content

Commit aba0c8d

Browse files
authored
Merge pull request #70 from fastify/no-number
skip non-coerceable numbers
2 parents 60fc96f + f4a1018 commit aba0c8d

File tree

5 files changed

+141
-18
lines changed

5 files changed

+141
-18
lines changed

index.js

+48-14
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,18 @@ function additionalProperty (schema, externalSchema, fullSchema) {
314314
} else if (type === 'integer') {
315315
code += `
316316
${addComma}
317-
json += $asString(keys[i]) + ':' + $asInteger(obj[keys[i]])
317+
var t = Number(obj[keys[i]])
318+
if (isLong && isLong(obj[keys[i]]) || !isNaN(t)) {
319+
json += $asString(keys[i]) + ':' + $asInteger(obj[keys[i]])
320+
}
318321
`
319322
} else if (type === 'number') {
320323
code += `
321-
${addComma}
322-
json += $asString(keys[i]) + ':' + $asNumber(obj[keys[i]])
324+
var t = Number(obj[keys[i]])
325+
if (!isNaN(t)) {
326+
${addComma}
327+
json += $asString(keys[i]) + ':' + t
328+
}
323329
`
324330
} else if (type === 'boolean') {
325331
code += `
@@ -364,22 +370,50 @@ function refFinder (ref, schema, externalSchema) {
364370

365371
function buildCode (schema, code, laterCode, name, externalSchema, fullSchema) {
366372
Object.keys(schema.properties || {}).forEach((key, i, a) => {
367-
// Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
368-
// see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
369-
code += `
370-
if (obj['${key}'] !== undefined) {
371-
${addComma}
372-
json += '${$asString(key)}:'
373-
`
374-
375373
if (schema.properties[key]['$ref']) {
376374
schema.properties[key] = refFinder(schema.properties[key]['$ref'], fullSchema, externalSchema)
377375
}
378376

379-
var result = nested(laterCode, name, key, schema.properties[key], externalSchema, fullSchema)
377+
// Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
378+
// see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
379+
380+
var type = schema.properties[key].type
381+
if (type === 'number') {
382+
code += `
383+
var t = Number(obj['${key}'])
384+
if (!isNaN(t)) {
385+
${addComma}
386+
json += '${$asString(key)}:' + t
387+
`
388+
} else if (type === 'integer') {
389+
code += `
390+
var rendered = false
391+
if (isLong && isLong(obj['${key}'])) {
392+
${addComma}
393+
json += '${$asString(key)}:' + obj['${key}'].toString()
394+
rendered = true
395+
} else {
396+
var t = Number(obj['${key}'])
397+
if (!isNaN(t)) {
398+
${addComma}
399+
json += '${$asString(key)}:' + t
400+
rendered = true
401+
}
402+
}
403+
404+
if (rendered) {
405+
`
406+
} else {
407+
code += `
408+
if (obj['${key}'] !== undefined) {
409+
${addComma}
410+
json += '${$asString(key)}:'
411+
`
380412

381-
code += result.code
382-
laterCode = result.laterCode
413+
var result = nested(laterCode, name, key, schema.properties[key], externalSchema, fullSchema)
414+
code += result.code
415+
laterCode = result.laterCode
416+
}
383417

384418
if (schema.required && schema.required.indexOf(key) !== -1) {
385419
code += `

test/additionalProperties.test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ test('additionalProperties - string coerce', (t) => {
9393
t.equal('{"foo":"true","ofoo":"42","arrfoo":"array,test","objfoo":"[object Object]"}', stringify(obj))
9494
})
9595

96-
test('additionalProperties - number coerce', (t) => {
96+
test('additionalProperties - number skip', (t) => {
9797
t.plan(1)
9898
const stringify = build({
9999
title: 'check number coerce',
@@ -105,7 +105,7 @@ test('additionalProperties - number coerce', (t) => {
105105
})
106106

107107
const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
108-
t.equal('{"foo":1,"ofoo":42,"xfoo":null,"arrfoo":null,"objfoo":null}', stringify(obj))
108+
t.equal(stringify(obj), '{"foo":1,"ofoo":42}')
109109
})
110110

111111
test('additionalProperties - boolean coerce', (t) => {
@@ -120,7 +120,7 @@ test('additionalProperties - boolean coerce', (t) => {
120120
})
121121

122122
const obj = { foo: 'true', ofoo: 0, arrfoo: [1, 2], objfoo: { a: true } }
123-
t.equal('{"foo":true,"ofoo":false,"arrfoo":true,"objfoo":true}', stringify(obj))
123+
t.equal(stringify(obj), '{"foo":true,"ofoo":false,"arrfoo":true,"objfoo":true}')
124124
})
125125

126126
test('additionalProperties - object coerce', (t) => {

test/basic.test.js

+30
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,36 @@ buildTest({
246246
readonly: true
247247
})
248248

249+
test('skip or coerce numbers and integers that are not numbers', (t) => {
250+
const stringify = build({
251+
'title': 'basic',
252+
'type': 'object',
253+
'properties': {
254+
'age': {
255+
'type': 'number'
256+
},
257+
'distance': {
258+
'type': 'integer'
259+
}
260+
}
261+
})
262+
263+
var result = stringify({
264+
age: 'hello ',
265+
distance: 'long'
266+
})
267+
268+
t.deepEqual(JSON.parse(result), {})
269+
270+
result = stringify({
271+
age: '42',
272+
distance: true
273+
})
274+
275+
t.deepEqual(JSON.parse(result), { age: 42, distance: 1 })
276+
t.end()
277+
})
278+
249279
test('Should throw on invalid schema', t => {
250280
t.plan(1)
251281
try {

test/long.test.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ test(`render an object with long as JSON`, (t) => {
4444
t.ok(validate(JSON.parse(output)), 'valid schema')
4545
})
4646

47-
test(`render aan array with long as JSON`, (t) => {
47+
test(`render an array with long as JSON`, (t) => {
4848
t.plan(2)
4949

5050
const schema = {
@@ -62,3 +62,24 @@ test(`render aan array with long as JSON`, (t) => {
6262
t.equal(output, '[18446744073709551615]')
6363
t.ok(validate(JSON.parse(output)), 'valid schema')
6464
})
65+
66+
test(`render an object with a long additionalProperty as JSON`, (t) => {
67+
t.plan(2)
68+
69+
const schema = {
70+
title: 'object with long',
71+
type: 'object',
72+
additionalProperties: {
73+
type: 'integer'
74+
}
75+
}
76+
77+
const validate = validator(schema)
78+
const stringify = build(schema)
79+
const output = stringify({
80+
num: Long.fromString('18446744073709551615', true)
81+
})
82+
83+
t.equal(output, '{"num":18446744073709551615}')
84+
t.ok(validate(JSON.parse(output)), 'valid schema')
85+
})

test/required.test.js

+38
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,41 @@ test('object with required field', (t) => {
4040
t.pass()
4141
}
4242
})
43+
44+
test('required numbers', (t) => {
45+
t.plan(3)
46+
47+
const schema = {
48+
title: 'object with required field',
49+
type: 'object',
50+
properties: {
51+
str: {
52+
type: 'string'
53+
},
54+
num: {
55+
type: 'integer'
56+
}
57+
},
58+
required: ['num']
59+
}
60+
const stringify = build(schema)
61+
62+
try {
63+
stringify({
64+
num: 42
65+
})
66+
t.pass()
67+
} catch (e) {
68+
t.fail()
69+
}
70+
71+
try {
72+
stringify({
73+
num: 'aaa'
74+
})
75+
t.fail()
76+
} catch (e) {
77+
t.is(e.message, 'num is required!')
78+
t.pass()
79+
}
80+
})

0 commit comments

Comments
 (0)