Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type coercion does not work with anyOf Number or Boolean #2348

Open
SeanReece opened this issue Nov 20, 2023 · 2 comments
Open

Type coercion does not work with anyOf Number or Boolean #2348

SeanReece opened this issue Nov 20, 2023 · 2 comments

Comments

@SeanReece
Copy link

TL;DR: I want a property to support either a boolean OR a number value. With coercion enabled, true will be coerced to 1 or 1 will be coerced to true depending on the order of the types in the anyOf.

What version of Ajv are you using? Does the issue happen if you use the latest version?

0.8.12

Ajv options object

const ajv = new Ajv({ coerceTypes: true })

JSON Schema

const schema = {
  type: 'object',
  properties: {
    foo: { anyOf: [{ type: 'boolean' }, { type: 'number' }] },  // Define boolean first
    bar: { anyOf: [{ type: 'number' }, { type: 'boolean' }] },  // Define number first
  },
  required: ['foo'],
  additionalProperties: false,
}

Sample data

const boolData = { foo: true, bar: true } // Results in { foo: true, bar: 1 } 
const numData = { foo: 1, bar: 1 } // results in { foo: true, bar: 1 }

What results did you expect?

const boolData = { foo: true, bar: true } // I expect { foo: true, bar: true } 
const numData = { foo: 1, bar: 1 } // I expect { foo: 1, bar: 1 }

Since coercion is done according to the order of the types in the schema, the resulting coerced type depends on whether boolean or number comes first, BUT I believe both results are incorrect.

The suggestion from this issue: #399 would have allowed us to fine tune coercion for this use case, but unfortunately I don't believe the suggestion to use keywords helps us in this case. I tried something similar to what was suggested in the comment in that issue but AJV still coerces the value after the keyword.

There must be something I'm missing here. This seems like a fairly common use case that seems broken. Please advise.

@epoberezkin
Copy link
Member

Type coercion is an attempt to apply imperative feature, that depends on order, to declarative schema. So you will indeed be getting different results for different order of coercions, and the options are to expect it or to use type with array of strings instead of anyOf.

@SeanReece
Copy link
Author

Hi @epoberezkin. Thanks for the response. My example here was purposefully simple just to get the point across but our implementation is quite complex, so doing something with an array of strings wouldn't really work. I mostly just wanted validation that keywords do not allow customizing coercion (as suggested in #399) as coercion will still be run after the keyword logic. Our solution for now is to switch to any in our fastify request schema, then later check what the type is supposed to be and do manual validation/coercion against a single type.

So we have found a solution for us, but I would still argue that having overlapping coercion rules with no way to customize the coercion is an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants