allow reversal and add more tests
parent
4d1aa5fe31
commit
ec09c3c735
|
@ -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 type →<br>to type ↓|string|number|boolean|null|
|
|from type →<br>to type ↓|string|number|boolean|null|
|
||||||
|
|
|
@ -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}}];
|
||||||
{{?}}
|
{{?}}
|
||||||
|
|
|
@ -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,32 +70,34 @@ var coercionRules = {
|
||||||
{ from: {}, to: undefined }
|
{ from: {}, to: undefined }
|
||||||
],
|
],
|
||||||
'array': [
|
'array': [
|
||||||
{ from: [], to: undefined }
|
{ from: [], to: undefined },
|
||||||
|
{ from: ['1'], to: undefined }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'boolean': {
|
||||||
|
'string': [
|
||||||
|
{ from: 'false', to: false },
|
||||||
|
{ from: 'true', to: true },
|
||||||
|
{ from: '', to: undefined },
|
||||||
|
{ from: 'abc', to: undefined }
|
||||||
|
],
|
||||||
|
'number': [
|
||||||
|
{ from: 0, to: false },
|
||||||
|
{ from: 1, to: true },
|
||||||
|
{ from: 2, to: undefined },
|
||||||
|
{ from: 2.5, to: undefined }
|
||||||
|
],
|
||||||
|
'null': [
|
||||||
|
{ from: null, to: false }
|
||||||
|
],
|
||||||
|
'object': [
|
||||||
|
{ from: {}, to: undefined }
|
||||||
|
],
|
||||||
|
'array': [
|
||||||
|
{ from: [], to: undefined },
|
||||||
|
{ from: [0], to: undefined }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'boolean': {
|
|
||||||
'string': [
|
|
||||||
{ from: 'false', to: false },
|
|
||||||
{ from: 'true', to: true },
|
|
||||||
{ from: '', to: undefined },
|
|
||||||
{ from: 'abc', to: undefined },
|
|
||||||
],
|
|
||||||
'number': [
|
|
||||||
{ from: 0, to: false },
|
|
||||||
{ from: 1, to: true },
|
|
||||||
{ from: 2, to: undefined },
|
|
||||||
{ from: 2.5, to: undefined }
|
|
||||||
],
|
|
||||||
'null': [
|
|
||||||
{ from: null, to: false }
|
|
||||||
],
|
|
||||||
'object': [
|
|
||||||
{ from: {}, to: undefined }
|
|
||||||
],
|
|
||||||
'array': [
|
|
||||||
{ from: [], to: undefined }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'null': {
|
'null': {
|
||||||
'string': [
|
'string': [
|
||||||
{ from: '', to: null },
|
{ from: '', to: null },
|
||||||
|
@ -112,17 +116,18 @@ var coercionRules = {
|
||||||
{ from: {}, to: undefined }
|
{ from: {}, to: undefined }
|
||||||
],
|
],
|
||||||
'array': [
|
'array': [
|
||||||
{ from: [], to: undefined }
|
{ from: [], to: undefined },
|
||||||
|
{ from: [null], to: undefined }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'array': {
|
'array': {
|
||||||
'all': [
|
'all': [
|
||||||
{ type: 'string', from: 'abc', to: undefined },
|
{ type: 'string', from: 'abc', to: undefined },
|
||||||
{ type: 'number', from: 1, to: undefined },
|
{ type: 'number', from: 1, to: undefined },
|
||||||
{ type: 'boolean', from: true, to: undefined },
|
{ type: 'boolean', from: true, to: undefined },
|
||||||
{ type: 'null', from: null, to: undefined },
|
{ type: 'null', from: null, to: undefined },
|
||||||
{ type: 'object', from: {}, to: undefined }
|
{ type: 'object', from: {}, to: undefined }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'object': {
|
'object': {
|
||||||
'all': [
|
'all': [
|
||||||
|
@ -135,24 +140,42 @@ var coercionRules = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var coercionArrayRules = {
|
var coercionArrayRules = JSON.parse(JSON.stringify(coercionRules));
|
||||||
'array': {
|
coercionArrayRules.string.array = [
|
||||||
'string': [
|
{ from: ['abc'], to: 'abc' }
|
||||||
{ from: 'abc', to: ['abc'] }
|
];
|
||||||
],
|
coercionArrayRules.number.array = [
|
||||||
'number': [
|
{ from: [1.5], to: 1.5 }
|
||||||
{ from: 1, to: [1] }
|
];
|
||||||
],
|
coercionArrayRules.integer.array = [
|
||||||
'boolean': [
|
{ from: [1], to: 1 }
|
||||||
{ from: true, to: [true] }
|
];
|
||||||
],
|
coercionArrayRules.boolean.array = [
|
||||||
'null': [
|
{ from: [true], to: true }
|
||||||
{ from: null, to: [null] }
|
];
|
||||||
],
|
coercionArrayRules.null.array = [
|
||||||
'object': [
|
{ from: [null], to: null }
|
||||||
{ from: {}, to: [{}] }
|
];
|
||||||
]
|
/*coercionArrayRules.object.array = [
|
||||||
}
|
{ from: [{}], to: {} }
|
||||||
|
];*/
|
||||||
|
|
||||||
|
coercionArrayRules.array = {
|
||||||
|
'string': [
|
||||||
|
{from: 'abc', to: ['abc']}
|
||||||
|
],
|
||||||
|
'number': [
|
||||||
|
{from: 1, to: [1]}
|
||||||
|
],
|
||||||
|
'boolean': [
|
||||||
|
{from: true, to: [true]}
|
||||||
|
],
|
||||||
|
'null': [
|
||||||
|
{from: null, to: [null]}
|
||||||
|
],
|
||||||
|
'object': [
|
||||||
|
{from: {}, to: [{}]}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Type coercion', function () {
|
describe('Type coercion', function () {
|
||||||
|
@ -175,19 +198,19 @@ 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 ];
|
||||||
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should coerce values in objects/arrays and update properties/items', function() {
|
it('should coerce values in objects/arrays and update properties/items', function() {
|
||||||
testRules(coercionRules, function (test, schema, canCoerce, toType, fromType) {
|
testRules(coercionRules, function (test, schema, canCoerce, toType, fromType) {
|
||||||
|
@ -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,19 +389,18 @@ 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;
|
||||||
if (canCoerce) {
|
if (canCoerce) {
|
||||||
if (Array.isArray(test.to)) {
|
if (Array.isArray(test.to)) {
|
||||||
schema = {type: toType, "items": { "type": fromType, "enum":[test.from] }};
|
schema = {type: toType, "items": { "type": fromType, "enum":[test.from] }};
|
||||||
} else {
|
} else {
|
||||||
schema = {type: toType, "enum": [test.to]};
|
schema = {type: toType, "enum": [test.to]};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
schema = { type: toType };
|
schema = { type: toType };
|
||||||
}
|
}
|
||||||
cb(test, schema, canCoerce, toType, fromType);
|
cb(test, schema, canCoerce, toType, fromType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue