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

Question regarding format & oneOf error validation object #427

Closed
krishnanms opened this issue Feb 24, 2017 · 4 comments
Closed

Question regarding format & oneOf error validation object #427

krishnanms opened this issue Feb 24, 2017 · 4 comments
Milestone

Comments

@krishnanms
Copy link

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

Ajv options object (see https://github.com/epoberezkin/ajv#options):

{
   jsonPointers: true,
   verbose: true
}

JSON Schema (please make it as small as possible to reproduce the issue):

{
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "foo": {
           "type": "string",
           "format": "ipv4"
        }
      },
      "required": [ "foo" ],
      "additionalProperties": false
    },
    {
      "properties": {
        "bar": {
           "type": "string",
           "format": "ipv4"
        }
      },
      "required": [ "bar" ],
      "additionalProperties": false
    }
  ]
}

Data (please make it as small as possible to reproduce the issue):

{
   "foo": "10.0.0.257"
}

Your code (please use options, schema and data as variables):

var options = {
   jsonPointers: true,
   verbose: true
};

var ajv = new Ajv(options);
var validate = ajv.compile(schema);
var valid = validate(data);

console.log(validate(data));
console.log(validate.errors);

https://runkit.com/krishnanms/58af9965e4edc300143368dd

Validation result, data AFTER validation, error messages:

[ { keyword: 'oneOf',
    dataPath: '',
    schemaPath: '#/oneOf',
    params: {},
    message: 'should match exactly one schema in oneOf',
    schema: [ [Object], [Object] ],
    parentSchema: { type: 'object', oneOf: [Object] },
    data: { foo: '10.0.0.257' } } ]

What results did you expect?
The message shows 'should match exactly one schema in oneOf', while the schema validation failed due to an invalid format for the ip address, shouldn't this be the keyword and cause for the validation failure rather than oneOf?

Are you going to resolve the issue?
I am not sure I can.

@epoberezkin
Copy link
Member

@krishnanms "oneOf" requires the data to be valid against exactly one schema, unlike "anyOf" that requires that data is valid against any of the schemas (i.e. possibly valid against more than one schema).

In general, the approach to error reporting is that if all the errors are fixed then the data will be valid against the schema. That is not the case with oneOf though. In your case if Ajv were to return the errors from schemas inside oneOf it would return:

  1. "foo" has wrong format (error from the first schema in oneOf)
  2. property "bar" is required (error from the second schema schema in oneOf)
  3. should match exactly one schema in oneOf

That's what Ajv would return if you used anyOf, by the way.
If you fix all these errors though (format of "foo" and add "bar") the data would still be invalid, because oneOf requires exactly one schema to be valid, not both.

That was the motivation to not report underlying errors from oneOf.

I will re-consider this decision, in the meanwhile you can:

  1. use anyOf (error report would include errors from both schemas though, as Ajv has no way of knowing which of the schemas is the right one)
  2. use conditional ("if/then/else" keywords, they is likely to be included in draft-07 and is available as part of ajv-keywords package). In this case you can "tell" Ajv how to choose which schema is the right one to use based on some subset of requirements (e.g., the field that is present) and in this way avoid including errors from both schemas in the report in case of failure.

In general it is always better to use "anyOf" in cases when schemas are mutually exclusive (both can't be valid at the same time), as in your case, and only use "oneOf" when you need to make sure that ONLY ONE schema is valid. "oneOf" will always validate data against ALL schemas, while "anyOf" always short circuits - as soon as the data is valid against some schema, validation of anyOf succeeds.

@krishnanms
Copy link
Author

@epoberezkin Thanks for the detailed response. I was able to work around this, by setting allErrors: true and using the first error object in the array, which shows a message with invalid format. Not sure if this is the right way to go about it, but works.

@epoberezkin
Copy link
Member

@krishnanms interesting. I didn't realise it depends on allErrors option, I don't think it should. This option affects continuing validation after the first failure that determines the validation result, and oneOf keyword is the first such failure in both cases. So it should be made consistent.

@epoberezkin epoberezkin added this to the 5.0.0 milestone Feb 24, 2017
@epoberezkin
Copy link
Member

If you decide to improve it please make PR to 5.0.0 branch.

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