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

addSchema() produces error when {nullable: true} #1171

Closed
maldimirov opened this issue Mar 13, 2020 · 7 comments
Closed

addSchema() produces error when {nullable: true} #1171

maldimirov opened this issue Mar 13, 2020 · 7 comments

Comments

@maldimirov
Copy link

Using nullable: true option when calling addSchema() an error is thrown:

Error: schema with key or id "" already exists

What version of Ajv are you using?
Ajv version: 6.12.0 (atm latest)

Example code to reproduce

const Ajv = require('ajv');

const schema = {
    type: 'string',
    nullable: true,
};
const value1 = 'string';
const value2 = null;

const ajv = new Ajv({nullable: true});
ajv.addSchema(schema, '#');
const valid1 = ajv.validate('#', value1);
const valid2 = ajv.validate('#', value2);

console.log(valid1);
console.log(valid2);

A bit more details
On the example code when you remove the nullable option everything works as expected and the console prints true and false. Setting the option to either nullable: true or nullable: false produces the error.

What results did you expect?
Not throwing error and console logging true 2 times.

Are you going to resolve the issue?
No, but I will provide a workaround in the comments.

@maldimirov
Copy link
Author

Workaround
A workaround is using compile(). E.g.

const ajv = new Ajv({nullable: true});
const validate = ajv.compile(schema);
const valid1 = validate(value1);
const valid2 = validate(value2);

So why use nullable and addSchema()?
We are using Ajv to validate API responses against an Open Api Schema definition and it's really convenient to do something like:

const ajv = new Ajv({nullable: true});
ajv.addSchema(apiDoc, '#')
  .validate('#/components/schemas/Details', response.body)

In this case the workaround we found is to "trick" compile() using a $ref like this:

const validate = ajv.compile({
   $ref: '#/components/schemas/Details',
   ...schema,
});
validate(response.body);

@epoberezkin
Copy link
Member

epoberezkin commented Mar 28, 2020

A better approach would be to give schema some ID and then using getSchema or validate:

ajv.addSchema(schema, 'foo')
validate = ajv.getSchema('foo#/components/schemas/Details')
validate(data)

// or
ajv.validate('foo#/components/schemas/Details', data)

@maldimirov
Copy link
Author

I thought a # is a valid schema name. Guess not :)
Your example works, but it would be good to have that documented somewhere. I could not find in the documentation any reference on what is a valid schema name, and that passing # will actually result in a schema without id.

@epoberezkin
Copy link
Member

epoberezkin commented Mar 29, 2020

schema id is URI with JSON pointer in hash fragment, so “foo” and “foo#” are treated as the same schema id. That’s why # on its own is an empty URI.

I am still not sure why it works without nullable and doesn’t work with it...

@maldimirov
Copy link
Author

Well, I leave it to you to decide whether this is a bug and the issue should remain open.

@epoberezkin
Copy link
Member

Yes, I want to investigate it at some point. It is definitely worth clarifying schema ID in docs, in line with the specification, in this section: https://github.com/epoberezkin/ajv#ref

All the examples there have full URI as schema IDs.

@jasoniangreen
Copy link
Collaborator

This works in the latest version.

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

No branches or pull requests

3 participants