vega / ts-json-schema-generator

Generate JSON schema from your Typescript sources
MIT License
1.38k stars 190 forks source link

How do you use ajv with references? #2003

Open bodinsamuel opened 2 weeks ago

bodinsamuel commented 2 weeks ago

Hi,

Sorry for the dumb question but I'm struggling a bit to use this package. I'm exporting multiple Typescript interface, so I end up with a file like this:

{
  "definitions": {
    "Test1": {
      "type": "object",
      "properties": {
        "nested": {"$ref": "#/definitions/Test2"}
      },
      "required": [ "nested" ],
      "additionalProperties": false
    },
    "Test2": {
      "type": "object",
      "properties": {
        "title": { "type": "string"}
      },
      "required": [ "title" ],
      "additionalProperties": false
    }
  }
}

However when it's time to actually use the json schema I'm lost. I tried using ajv but I'm failing to understand how to validate one interface with a Reference using this json schema. There is no documentation regarding this use case so I'm wondering.

const ajv = new Ajv({ allErrors: true, discriminator: true });
const validate = ajv.compile(jsonSchema); // the one above

// Validate against Test1
validate({ nested: { title: 'foobar' }}); 

Without a reference I can just load the schema with the appropriate key but when there is references it won't work

const ajv = new Ajv({ allErrors: true, discriminator: true });
const validate = ajv.compile(jsonSchema["definitions"]["Test2"]);

// Validate against Test2 directly
validate({ title: 'foobar' }); 

Is there any way to tell ajv to validate Test1 inside the schema? Or any other way to achieve that.

Thanks ☺️

arthurfiorette commented 2 weeks ago

Hey @bodinsamuel, you can iterate over each definitions property and add them into your ajv with addSchema.

dbergey commented 6 days ago

@bodinsamuel Were you able to make this solution work? If so, would you mind posting some sample code? I have a similar issue and the iteration solution isn't working for me.

bodinsamuel commented 6 days ago

hey I didn't managed to make the addSchema works (but I didn't took much time looking at it), I did that:

const ajv = new Ajv({ allErrors: true, discriminator: true });
addFormats(ajv);
const validator = ajv.compile({ ...jsonSchema, ...jsonSchema['definitions'][modelName] });

Basically it append the model at the root level and keep the definitions property accessible at the same level, so no need to change anything

dbergey commented 6 days ago

Thanks for replying so quickly! It turns out I was also being hit by this bug: https://github.com/vega/ts-json-schema-generator/issues/1732

When $refs were properly qualified with the schema id, then this structure worked:

const ajv = new AJV();
ajv.addSchema(mySchema, "mySchemaId");
const validate = ajv.compile<MyExportedType>(mySchema.definitions.MyExportedType);