danvk
danvk

Reputation: 16955

Validate using a specific definition with ajv

I have a JSON Schema file describing my API. It consists of some definitions as well as some vestigial parts from codegen that I'd like to ignore (the properties and required fields):

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "CreateBook": {
      "properties": {
        "title": {"type": "string"},
        "author": {"type": "string"},
        "numPages": {"type": "number"}
      },
      "required": ["title", "author"]
    },
    "CreateShelf": {
      "properties": {
        "books": {"type": "array", "items": {"type": "string"}}
      },
      "required": ["books"]
    }
  },
  "properties": {
    "/api/create-book": {
      "properties": {"type": {"post": {"$ref": "#/definitions/CreateBook"}}},
      "required": ["post"],
      "type": "object"
    },
    "/api/create-shelf": {
      "properties": {"type": {"post": {"$ref": "#/definitions/CreateShelf"}}},
      "required": ["post"],
      "type": "object"
    }
  },
  "required": ["/api/create-book", "/api/create-shelf"],
  "type": "object"
}

I'd like to validate requests according to the definitions. I'd like to completely ignore the properties and required fields, which describe the shape of the API itself, not the individual requests.

Given what I expect to be a CreateBook request and this JSON schema, how should I validate it?

Here's what I tried:

const ajv = new Ajv();
const validate = ajv.compile(jsonSchema);

const body = {
  author: 'Roald Dahl',
  numPages: 234,
  // missing title
};

if (!validate(body, '#/definitions/CreateBook')) {
  console.log(validate.errors);
}

This logs:

[
  {
    keyword: 'required',
    dataPath: '#/definitions/CreateBook',
    schemaPath: '#/required',
    params: { missingProperty: '/api/create-book' },
    message: "should have required property '/api/create-book'"
  }
]

So it's ignoring the dataPath parameter ('#/definitions/CreateBook'). What's the right way to do this? Do I need to create a new schema for every request type?

Upvotes: 3

Views: 2319

Answers (1)

Jason Desrosiers
Jason Desrosiers

Reputation: 24489

If you use addSchema instead of compile to compile the schema, you can specify a fragment.

const ajv = new Ajv();
ajv.addSchema(jsonSchema);
const validate = ajv.getSchema("#/definitions/CreateBook");

const body = {
  author: 'Roald Dahl',
  numPages: 234,
  // missing title
};

if (!validate(body)) {
  console.log(validate.errors);
}

Upvotes: 8

Related Questions