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

useDefaults doesn't work with conditional requires #2456

Closed
Timberbain opened this issue Jun 18, 2024 · 3 comments
Closed

useDefaults doesn't work with conditional requires #2456

Timberbain opened this issue Jun 18, 2024 · 3 comments

Comments

@Timberbain
Copy link

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

Ajv options object

const ajv = new Ajv({
  allErrors: true,
  useDefaults: true,
  strict: false,
});

JSON Schema

const schema = {
  type: 'object',
  properties: {
    useInterconnect: {
      type: 'boolean',
      default: false,
    },
    interconnectId: {
      type: 'string',
    },
  },
  allOf: [
    {
      if: {
        type: 'object',
        properties: {
          useInterconnect: { const: true },
        },
      },
      then: {
        required: ['interconnectId'],
      },
    },
  ],
};

Sample data

const data = {};

Your code

https://runkit.com/timberbain/6671765baad1af0008237f25

const validate = ajv.compile(schema);

const valid = validate(data);
console.log(data); // Log: { useInterconnect: false }

if (valid) {
  console.log('Data is valid:', data);
} else {
  console.log('Data is invalid:', validate.errors);
}

Validation result, data AFTER validation, error messages

 Data is invalid: [
  {
    instancePath: '',
    schemaPath: '#/allOf/0/then/required',
    keyword: 'required',
    params: { missingProperty: 'interconnectId' },
    message: "must have required property 'interconnectId'"
  },
  {
    instancePath: '',
    schemaPath: '#/allOf/0/if',
    keyword: 'if',
    params: { failingKeyword: 'then' },
    message: 'must match "then" schema'
  }
]

What results did you expect?
I expected no validation errors as useInterconnect has been defaulted to false.

Previously running the same code with version 6.12.6 (without the strict option as it was introduced in later version) the schema is considered valid. But after migrating to version 8.16.0, the data is no longer valid according to the schema.

@jasoniangreen
Copy link
Collaborator

I need to look into it more but given that default is not supported inside a allOf, maybe there are other limitations when using it alongside an allOf. It does indeed look like the behaviour is incorrect because if I pass { useInterconnect: false } back in it validates fine.

This page explains the uncertainties when dealing with schemas that both modify and validate the data.
https://ajv.js.org/guide/modifying-data.html

With that being said, this may be a bug and may be fixable, so I will try and get my head around it.

@Timberbain
Copy link
Author

Super nice, appreciate it. We have been running 6.12.6 for some time now and want to migrate to version 8, but this breaking behaviour is currently blocking the upgrade. Thanks!

@jasoniangreen
Copy link
Collaborator

After looking into this and discussing with @epoberezkin this will be a "nofix" unfortunately. If you look at the big red warning on this page you'll see that order of evaluation, which may possibly be the thing that changed between version 6 and 8 to make this start failing for you, is not something we can guarantee or document. This is the sort of problem you will always run into when you expect a single declarative schema to do imperative operations (such as "set defaults" followed by "validate the data").

Normally the best suggestion if you want to guarantee order of operations is to use allOf schema as it will do exactly that. In this case, defaults can't be used inside an allOf so I would suggest splitting into two schemas. One that manages defaults and another that validates. This can also be easier to reason about.

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