Matching type order
Prerequisites
- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the issue has not already been raised
Issue
There are some places where we need to match the type before serializing the data: oneOf, anyOf, and when the type property is an array. The problem is that matching the types is not always mutually exclusive.
Here is the first problem. If a value isn't marked as nullable we should coerce the null value to the value schema type. integer -> 0 number -> 0 string -> "" boolean -> false
What should we do if there are multiple types?
test('nullable string value', (t) => {
t.plan(1)
const schema = {
type: ['string', 'number']
}
const stringify = build(schema)
const value = stringify(null)
t.equal(value, '""')
})
test('nullable number value', (t) => {
t.plan(1)
const schema = {
type: ['number', 'string']
}
const stringify = build(schema)
const value = stringify(null)
t.equal(value, '0')
})
Should we match types in the order in which they are declared?
- loop through the
oneOf / anyOfarray, and check if type match - If one of the type match, serialize
- If all of them do not match, fallback to first one
What if few of them match?
What if few of them match?
it should actually break when the first one match. the order is important in serialization.
We need to declare somewhere that the order is important in this case.
Another unclear case. If I define a typed property it will always coerce the value to the defined type, if I add another type, coercion will not work.
test('integer type', (t) => {
t.plan(1)
const schema = {
type: 'integer'
}
const stringify = build(schema)
const value = stringify('42')
t.equal(value, '42')
})
test('integer or boolean type', (t) => {
t.plan(1)
const schema = {
type: ['integer', 'boolean']
}
const stringify = build(schema)
const value = stringify('42')
t.equal(value, '42') // fails
})
In my point of view, array of type should behave like oneOf.
oneOf has the same issue. It doesn't coerce type by default.
oneOfhas the same issue. It doesn't coerce type by default.
Yes, because oneOf really means one of the array.
If non of them is match, then the input do not match what this user want.
But, it can be coerce by enable the ajv coerceTypes option. It will always coerce to the first matching type.
So this is the correct behavior? https://github.com/fastify/fast-json-stringify/issues/450#issuecomment-1143448071
So this is the correct behavior? #450 (comment)
I would say yes.
If it need to be coerce by default. It means we need to implement a set of rules, how to determine it can be coerce (it may always match the first type). And do the checking.
I think it will be a very heavy job and significant impact the performance.