Skip to content

Commit 4bec21e

Browse files
fix: throw an error if cannot convert value to number (#433)
1 parent 77114f0 commit 4bec21e

File tree

4 files changed

+37
-57
lines changed

4 files changed

+37
-57
lines changed

index.js

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,15 @@ class Serializer {
8686
if (typeof i === 'bigint') {
8787
return i.toString()
8888
} else if (Number.isInteger(i)) {
89-
return this.asNumber(i)
89+
return '' + i
9090
} else {
9191
/* eslint no-undef: "off" */
92-
return this.asNumber(this.parseInteger(i))
92+
const integer = this.parseInteger(i)
93+
if (Number.isNaN(integer)) {
94+
throw new Error(`The value "${i}" cannot be converted to an integer.`)
95+
} else {
96+
return '' + integer
97+
}
9398
}
9499
}
95100

@@ -99,8 +104,8 @@ class Serializer {
99104

100105
asNumber (i) {
101106
const num = Number(i)
102-
if (isNaN(num)) {
103-
return 'null'
107+
if (Number.isNaN(num)) {
108+
throw new Error(`The value "${i}" cannot be converted to a number.`)
104109
} else {
105110
return '' + num
106111
}
@@ -725,7 +730,7 @@ function buildCode (location, code, laterCode, name) {
725730
const schema = location.schema
726731
const required = schema.required || []
727732

728-
Object.keys(schema.properties || {}).forEach((key, i, a) => {
733+
Object.keys(schema.properties || {}).forEach((key) => {
729734
let propertyLocation = mergeLocation(location, { schema: schema.properties[key] })
730735
if (schema.properties[key].$ref) {
731736
propertyLocation = refFinder(schema.properties[key].$ref, location)
@@ -735,45 +740,18 @@ function buildCode (location, code, laterCode, name) {
735740
// Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
736741
// see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
737742

738-
const type = schema.properties[key].type
739-
const nullable = schema.properties[key].nullable
740743
const sanitized = JSON.stringify(key)
741744
const asString = JSON.stringify(sanitized)
742745

743-
if (nullable) {
744-
code += `
745-
if (obj[${sanitized}] === null) {
746-
${addComma}
747-
json += ${asString} + ':null'
748-
} else {
749-
`
750-
}
751-
752-
if (type === 'number') {
753-
code += `
754-
var t = Number(obj[${sanitized}])
755-
if (!isNaN(t)) {
756-
${addComma}
757-
json += ${asString} + ':' + t
758-
`
759-
} else if (type === 'integer') {
760-
code += `
761-
var t = serializer.asInteger(obj[${sanitized}])
762-
if (!isNaN(t)) {
763-
${addComma}
764-
json += ${asString} + ':' + t
746+
code += `
747+
if (obj[${sanitized}] !== undefined) {
748+
${addComma}
749+
json += ${asString} + ':'
765750
`
766-
} else {
767-
code += `
768-
if (obj[${sanitized}] !== undefined) {
769-
${addComma}
770-
json += ${asString} + ':'
771-
`
772751

773-
const result = nested(laterCode, name, key, mergeLocation(propertyLocation, { schema: schema.properties[key] }), undefined, false)
774-
code += result.code
775-
laterCode = result.laterCode
776-
}
752+
const result = nested(laterCode, name, key, mergeLocation(propertyLocation, { schema: schema.properties[key] }), undefined, false)
753+
code += result.code
754+
laterCode = result.laterCode
777755

778756
const defaultValue = schema.properties[key].default
779757
if (defaultValue !== undefined) {
@@ -792,12 +770,6 @@ function buildCode (location, code, laterCode, name) {
792770
code += `
793771
}
794772
`
795-
796-
if (nullable) {
797-
code += `
798-
}
799-
`
800-
}
801773
})
802774

803775
for (const requiredProperty of required) {

test/basic.test.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ buildTest({
261261
readonly: true
262262
})
263263

264-
test('skip or coerce numbers and integers that are not numbers', (t) => {
264+
test('throw an error or coerce numbers and integers that are not numbers', (t) => {
265265
const stringify = build({
266266
title: 'basic',
267267
type: 'object',
@@ -275,14 +275,14 @@ test('skip or coerce numbers and integers that are not numbers', (t) => {
275275
}
276276
})
277277

278-
let result = stringify({
279-
age: 'hello ',
280-
distance: 'long'
281-
})
282-
283-
t.same(JSON.parse(result), {})
278+
try {
279+
stringify({ age: 'hello ', distance: 'long' })
280+
t.fail('should throw an error')
281+
} catch (err) {
282+
t.ok(err)
283+
}
284284

285-
result = stringify({
285+
const result = stringify({
286286
age: '42',
287287
distance: true
288288
})

test/patternProperties.test.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ test('patternProperties - string coerce', (t) => {
6363
})
6464

6565
test('patternProperties - number coerce', (t) => {
66-
t.plan(1)
66+
t.plan(2)
6767
const stringify = build({
6868
title: 'check number coerce',
6969
type: 'object',
@@ -75,8 +75,16 @@ test('patternProperties - number coerce', (t) => {
7575
}
7676
})
7777

78-
const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
79-
t.equal(stringify(obj), '{"foo":1,"ofoo":42,"xfoo":null,"arrfoo":null,"objfoo":null}')
78+
const coercibleValues = { foo: true, ofoo: '42' }
79+
t.equal(stringify(coercibleValues), '{"foo":1,"ofoo":42}')
80+
81+
const incoercibleValues = { xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
82+
try {
83+
stringify(incoercibleValues)
84+
t.fail('should throw an error')
85+
} catch (err) {
86+
t.ok(err)
87+
}
8088
})
8189

8290
test('patternProperties - boolean coerce', (t) => {

test/required.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ test('required numbers', (t) => {
232232
})
233233
t.fail()
234234
} catch (e) {
235-
t.equal(e.message, '"num" is required!')
235+
t.equal(e.message, 'The value "aaa" cannot be converted to an integer.')
236236
t.pass()
237237
}
238238
})

0 commit comments

Comments
 (0)