Skip to content

Commit

Permalink
Add support for options.allowNaN
Browse files Browse the repository at this point in the history
  • Loading branch information
Ajaxy committed Jan 17, 2019
1 parent b0b460a commit cfb2540
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -3,6 +3,15 @@

The way to cast data to types specified with [JSON schema](http://json-schema.org/).


### Arguments
- `source (object)` - Source object to be casted.
- `schema (object)` - JSON schema containing types definitions.
- `options (object)`
- `allowNaN` — Whether or not to return `NaN` for non-parseable numbers. The default is `false` which will cast `NaN` to `0`.

### Example

May be used for query params casting:

```js
Expand Down
20 changes: 11 additions & 9 deletions lib/index.js
@@ -1,17 +1,17 @@
function castWithSchema(query, schema) {
function castWithSchema(source, schema, options = {}) {
const casted = {};

Object.keys(query).forEach((field) => {
const value = query[field];
Object.keys(source).forEach((field) => {
const value = source[field];
const propertyDef = schema.properties && schema.properties[field];

casted[field] = castProp(value, propertyDef);
casted[field] = castProp(value, propertyDef, options);
});

return casted;
}

function castProp(value, propertyDef) {
function castProp(value, propertyDef, options = {}) {
if (!propertyDef || value === undefined) {
return value;
}
Expand All @@ -24,15 +24,17 @@ function castProp(value, propertyDef) {

switch (resolveType(realDef)) {
case 'integer':
return parseInt(value, 10) || 0;
const int = parseInt(value, 10);
return options.allowNaN ? int : (int || 0);
case 'number':
return parseFloat(value) || 0;
const float = parseFloat(value);
return options.allowNaN ? float : (float || 0);
case 'boolean':
return value !== 'false';
case 'array':
return Array.isArray(value) ? value.map(member => castProp(member, realDef.items)) : undefined;
return Array.isArray(value) ? value.map(member => castProp(member, realDef.items, options)) : undefined;
case 'object':
return typeof value === 'object' ? castWithSchema(value, realDef) : undefined;
return typeof value === 'object' ? castWithSchema(value, realDef, options) : undefined;
default:
return value;
}
Expand Down
78 changes: 78 additions & 0 deletions tests/allowNaN.test.js
@@ -0,0 +1,78 @@
const castWithSchema = require('../lib/index');

describe('All', () => {
it('Works', () => {
expect(castWithSchema({
b: '777',
c: '7.77',
d1: '777d',
d2: '777d',
e: '777',
q: 'invalid-number',
s: ['777', '7.77', 'invalid-number'],
s2: ['777', '7.77', 'invalid-number'], // array when `null` allowed
x: '',
y: '',
}, {
type: 'object',
properties: {
b: {
type: 'integer',
},
c: {
type: 'number',
},
d1: {
type: 'integer',
},
d2: {
type: 'number',
},
e: {
type: 'string',
},
q: {
type: 'number',
},
s: {
type: 'array',
items: {
type: 'number',
},
},
s2: {
anyOf: [
{
type: 'array',
items: {
type: 'number',
},
},
{
type: 'null',
},
],
},
x: {
type: 'integer',
},
y: {
type: 'number',
},
},
}, {
allowNaN: true,
})).toEqual({
b: 777,
c: 7.77,
d1: 777,
d2: 777,
e: '777',
q: NaN,
s: [777, 7.77, NaN],
s2: [777, 7.77, NaN],
x: NaN,
y: NaN,
});
});
});

0 comments on commit cfb2540

Please sign in to comment.