Ajv: Validate array items by $ref

Created on 31 Dec 2017  ·  4Comments  ·  Source: ajv-validator/ajv

What version of Ajv are you using? Does the issue happen if you use the latest version?
I'm using the latest Ajv with jsonschema draft-04.

Ajv reader

const fetch = require('node-fetch')
const Ajv = require('ajv');
const draft04 = require('ajv/lib/refs/json-schema-draft-04.json')

const loadSchema = (uri) => fetch(uri).then(res => res.json());

function (url, options = {}) {
  return async function validationHook (hook) {
    const schema = await fetch(url).then(res => res.json());
    const ajv = new Ajv(Object.assign({}, {loadSchema, allErrors: true}, options));
    ajv.addMetaSchema(draft04);
    const validator = new Promise( (resolve, reject) => {
      try {
        resolve(ajv.compileAsync(schema))
      } catch (error) {
        reject(error)
      }
    })

    validator.catch(() => {
      throw new errors.Unprocessable('Invalid schema');
      return hook
    })

    if (hook.data) {      
      return validator.then( validate => {
        hook.params.validated = validate(hook.data)
        if (!hook.params.validated) {
          throw new errors.Unprocessable('Invalid request data', {
            errors: validate.errors
          })
        }
        return hook;
      })
    }
    return hook;
  };
};

JSON Schema

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "id": "http://localhost:3030/fhir/Patient.schema.json",
  "allOf": [{
    "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.",
    "properties": {
      "name": {
        "description": "A name associated with the individual.",
        "type": "array",
        "items": {
          "$ref":  "HumanName.schema.json"
        }
      }
    },
    "required": ["name"]
  }]
}
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "id": "http://localhost:3030/fhir/HumanName.schema.json",
  "allOf": [{
    "description": "A human's name with the ability to identify parts and usage.",
    "properties": {
      "given": {
        "description": "Given name.",
        "type": "integer"
      }
    },
    "required": ["given"]
  }]
}

Expected result (It's always valid)
Invalid
curl 'http://localhost:3030/patients/' -H 'Content-Type: application/json' --data-binary '{ "name": ["It should be an integer"]}'
Valid
curl 'http://localhost:3030/patients/' -H 'Content-Type: application/json' --data-binary '{ "name": [{"given":1},{"given":2}]}'

JSON schema format
I'm new to jsonschema, what I'm trying to do is to make the fhir schemas work with ajv.
There are things that I didn't quite understand. For example:

  • allOf can be present even if there is only one definition.
  • definitions: should be used only when there are more object definitions in a single file?
  • did I made errors in the samples schema?

Most helpful comment

@chharvey means that “type” keyword in the same subschema as $ref is ignored - that’s by the JSON Schema specification.

There is an option to override this and either to fail or to take it into account. Also, there is good chance that the spec will change in that regard and the keywords in the same schema will not be ignored.

All 4 comments

I did solve the problem.
It was a mistake on my json schema.
This is the correct solution.

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "id": "http://localhost:3030/fhir/Patient.schema.json",
  "allOf": [{
    "description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services.",
    "properties": {
      "name": {
        "description": "A name associated with the individual.",
        "type": "array",
        "items": {
          "type": "object",
          "$ref": "HumanName.schema.json"
        }
      }
    },
    "required": ["name"]
  }]
}

2018 starts well :satisfied:. Happy New Year!!! :beers:

@gpietro It looks like the only change you made was add "type": "object", but I don't understand how that could've solved your problem. When an object schema has a "$ref" property, other properties are ignored.

All other properties in a "$ref" object MUST be ignored.

~ JSON Schema Core Specification

What else did you change to make it work?

$ref actually is a reference to another schema.
What you mean when you say that other properties are ignored?
I didn't change anything else. I had to specify the type of the $ref schema. In this case of type object.
$ref can refer as an URI to a local or remote file or inside definitions with '#'.

@chharvey means that “type” keyword in the same subschema as $ref is ignored - that’s by the JSON Schema specification.

There is an option to override this and either to fail or to take it into account. Also, there is good chance that the spec will change in that regard and the keywords in the same schema will not be ignored.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JonathanWilbur picture JonathanWilbur  ·  3Comments

darrin picture darrin  ·  5Comments

vivekgalatage picture vivekgalatage  ·  5Comments

mhelvens picture mhelvens  ·  5Comments

jabberwo picture jabberwo  ·  7Comments