allow reversal and add more tests

master
will Farrell 2016-07-24 19:03:27 -06:00
parent 4d1aa5fe31
commit ec09c3c735
3 changed files with 117 additions and 86 deletions

View File

@ -11,8 +11,6 @@ Type coercion only happens if there is `type` keyword and if without coercion th
If there are multiple types allowed in `type` keyword the coercion will only happen if none of the types match the data and some of the scalar types are present (coercion to/from `object`/`array` is not possible). In this case the validating function will try coercing the data to each type in order until some of them succeeds. If there are multiple types allowed in `type` keyword the coercion will only happen if none of the types match the data and some of the scalar types are present (coercion to/from `object`/`array` is not possible). In this case the validating function will try coercing the data to each type in order until some of them succeeds.
If `coerceTypes` is set to `array`
Possible type coercions: Possible type coercions:
|from&nbsp;type&nbsp;&rarr;<br>to&nbsp;type&nbsp;&darr;|string|number|boolean|null| |from&nbsp;type&nbsp;&rarr;<br>to&nbsp;type&nbsp;&darr;|string|number|boolean|null|

View File

@ -4,6 +4,10 @@
, $coerced = 'coerced' + $lvl; , $coerced = 'coerced' + $lvl;
}} }}
var {{=$dataType}} = typeof {{=$data}}; var {{=$dataType}} = typeof {{=$data}};
{{? it.opts.coerceTypes === 'array'}}
if ({{=$dataType}} === 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';
{{?}}
var {{=$coerced}} = undefined; var {{=$coerced}} = undefined;
{{ var $bracesCoercion = ''; }} {{ var $bracesCoercion = ''; }}
@ -13,25 +17,32 @@
{{ $bracesCoercion += '}'; }} {{ $bracesCoercion += '}'; }}
{{?}} {{?}}
{{? it.opts.coerceTypes === 'array' && $type !== 'array' }}
if ({{=$dataType}} === 'array' && {{=$data}}.length === 1) {
{{=$coerced}} = {{=$data}} = {{=$data}}[0];
{{=$dataType}} = typeof {{=$data}};
/*if ({{=$dataType}} === 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';*/
}
{{?}}
{{? $type == 'string' }} {{? $type === 'string' }}
if ({{=$dataType}} == 'number' || {{=$dataType}} == 'boolean') if ({{=$dataType}} === 'number' || {{=$dataType}} === 'boolean')
{{=$coerced}} = '' + {{=$data}}; {{=$coerced}} = '' + {{=$data}};
else if ({{=$data}} === null) {{=$coerced}} = ''; else if ({{=$data}} === null) {{=$coerced}} = '';
{{?? $type == 'number' || $type == 'integer' }} {{?? $type === 'number' || $type === 'integer' }}
if ({{=$dataType}} == 'boolean' || {{=$data}} === null if ({{=$dataType}} === 'boolean' || {{=$data}} === null
|| ({{=$dataType}} == 'string' && {{=$data}} && {{=$data}} == +{{=$data}} || ({{=$dataType}} === 'string' && {{=$data}} && {{=$data}} == +{{=$data}}
{{? $type == 'integer' }} && !({{=$data}} % 1){{?}})) {{? $type === 'integer' }} && !({{=$data}} % 1){{?}}))
{{=$coerced}} = +{{=$data}}; {{=$coerced}} = +{{=$data}};
{{?? $type == 'boolean' }} {{?? $type === 'boolean' }}
if ({{=$data}} === 'false' || {{=$data}} === 0 || {{=$data}} === null) if ({{=$data}} === 'false' || {{=$data}} === 0 || {{=$data}} === null)
{{=$coerced}} = false; {{=$coerced}} = false;
else if ({{=$data}} === 'true' || {{=$data}} === 1) else if ({{=$data}} === 'true' || {{=$data}} === 1)
{{=$coerced}} = true; {{=$coerced}} = true;
{{?? $type == 'null' }} {{?? $type === 'null' }}
if ({{=$data}} === '' || {{=$data}} === 0 || {{=$data}} === false) if ({{=$data}} === '' || {{=$data}} === 0 || {{=$data}} === false)
{{=$coerced}} = null; {{=$coerced}} = null;
{{?? $type === 'array' }} {{?? it.opts.coerceTypes === 'array' && $type === 'array' }}
if ({{=$dataType}} !== 'array') if ({{=$dataType}} !== 'array')
{{=$coerced}} = [{{=$data}}]; {{=$coerced}} = [{{=$data}}];
{{?}} {{?}}

View File

@ -22,7 +22,8 @@ var coercionRules = {
{ from: {}, to: undefined } { from: {}, to: undefined }
], ],
'array': [ 'array': [
{ from: [], to: undefined } { from: [], to: undefined },
{ from: [1], to: undefined }
] ]
}, },
'number': { 'number': {
@ -45,7 +46,8 @@ var coercionRules = {
{ from: {}, to: undefined } { from: {}, to: undefined }
], ],
'array': [ 'array': [
{ from: [], to: undefined } { from: [], to: undefined },
{ from: [true], to: undefined }
] ]
}, },
'integer': { 'integer': {
@ -68,7 +70,8 @@ var coercionRules = {
{ from: {}, to: undefined } { from: {}, to: undefined }
], ],
'array': [ 'array': [
{ from: [], to: undefined } { from: [], to: undefined },
{ from: ['1'], to: undefined }
] ]
}, },
'boolean': { 'boolean': {
@ -76,7 +79,7 @@ var coercionRules = {
{ from: 'false', to: false }, { from: 'false', to: false },
{ from: 'true', to: true }, { from: 'true', to: true },
{ from: '', to: undefined }, { from: '', to: undefined },
{ from: 'abc', to: undefined }, { from: 'abc', to: undefined }
], ],
'number': [ 'number': [
{ from: 0, to: false }, { from: 0, to: false },
@ -91,7 +94,8 @@ var coercionRules = {
{ from: {}, to: undefined } { from: {}, to: undefined }
], ],
'array': [ 'array': [
{ from: [], to: undefined } { from: [], to: undefined },
{ from: [0], to: undefined }
] ]
}, },
'null': { 'null': {
@ -112,7 +116,8 @@ var coercionRules = {
{ from: {}, to: undefined } { from: {}, to: undefined }
], ],
'array': [ 'array': [
{ from: [], to: undefined } { from: [], to: undefined },
{ from: [null], to: undefined }
] ]
}, },
'array': { 'array': {
@ -135,24 +140,42 @@ var coercionRules = {
} }
}; };
var coercionArrayRules = { var coercionArrayRules = JSON.parse(JSON.stringify(coercionRules));
'array': { coercionArrayRules.string.array = [
{ from: ['abc'], to: 'abc' }
];
coercionArrayRules.number.array = [
{ from: [1.5], to: 1.5 }
];
coercionArrayRules.integer.array = [
{ from: [1], to: 1 }
];
coercionArrayRules.boolean.array = [
{ from: [true], to: true }
];
coercionArrayRules.null.array = [
{ from: [null], to: null }
];
/*coercionArrayRules.object.array = [
{ from: [{}], to: {} }
];*/
coercionArrayRules.array = {
'string': [ 'string': [
{ from: 'abc', to: ['abc'] } {from: 'abc', to: ['abc']}
], ],
'number': [ 'number': [
{ from: 1, to: [1] } {from: 1, to: [1]}
], ],
'boolean': [ 'boolean': [
{ from: true, to: [true] } {from: true, to: [true]}
], ],
'null': [ 'null': [
{ from: null, to: [null] } {from: null, to: [null]}
], ],
'object': [ 'object': [
{ from: {}, to: [{}] } {from: {}, to: [{}]}
] ]
}
}; };
describe('Type coercion', function () { describe('Type coercion', function () {
@ -175,7 +198,7 @@ describe('Type coercion', function () {
}); });
}); });
it('should coerce scalar values in array', function() { it('should coerce scalar values (coerceTypes = array)', function() {
ajv = new Ajv({ coerceTypes: 'array', verbose: true }); ajv = new Ajv({ coerceTypes: 'array', verbose: true });
fullAjv = new Ajv({ coerceTypes: 'array', verbose: true, allErrors: true }); fullAjv = new Ajv({ coerceTypes: 'array', verbose: true, allErrors: true });
instances = [ ajv, fullAjv ]; instances = [ ajv, fullAjv ];
@ -183,7 +206,7 @@ describe('Type coercion', function () {
testRules(coercionArrayRules, function (test, schema, canCoerce, toType, fromType) { testRules(coercionArrayRules, function (test, schema, canCoerce, toType, fromType) {
instances.forEach(function (ajv) { instances.forEach(function (ajv) {
var valid = ajv.validate(schema, test.from); var valid = ajv.validate(schema, test.from);
//if (valid !== canCoerce) console.log('array', toType, fromType, test, ajv.errors); //if (valid !== canCoerce) console.log(toType, '.', fromType, test, schema, ajv.errors);
valid. should.equal(canCoerce); valid. should.equal(canCoerce);
}); });
}); });
@ -217,7 +240,7 @@ describe('Type coercion', function () {
function testCoercion(schema, fromData, toData) { function testCoercion(schema, fromData, toData) {
var valid = ajv.validate(schema, fromData); var valid = ajv.validate(schema, fromData);
// if (valid !== canCoerce) console.log(schema, fromData, toData); //if (valid !== canCoerce) console.log(schema, fromData, toData);
valid. should.equal(canCoerce); valid. should.equal(canCoerce);
if (valid) fromData.should.eql(toData); if (valid) fromData.should.eql(toData);
} }
@ -366,7 +389,6 @@ describe('Type coercion', function () {
for (var toType in rules) { for (var toType in rules) {
for (var fromType in rules[toType]) { for (var fromType in rules[toType]) {
var tests = rules[toType][fromType]; var tests = rules[toType][fromType];
//if (toType === 'array') { console.log(toType, fromType, tests); }
tests.forEach(function (test) { tests.forEach(function (test) {
var canCoerce = test.to !== undefined; var canCoerce = test.to !== undefined;
var schema; var schema;