Customized schema resolving for invalid objects with AJV

764 views Asked by At

I'm trying to find a way to alter schema validation to find most appropriate schema for a given object. Let's say we have a schema:

{
  "oneOf": [
    {
      "$ref": "#/definitions/a"
    },
    {
      "$ref": "#/definitions/b"
    }
  ],
  "definitions": {
    "a": {
      "type": "object",
      "properties": {
        "prop1": {
          "enum": ["x"]
        }
      },
      "required": ["prop1"]
    },
    "b": {
      "type": "object",
      "properties": {
        "prop1": {
          "enum": ["y"]
        },
        "prop2": {
          "type": "string"
        }
      },
      "required": ["prop1", "prop2"]
    }
  }
}

Now, if I have an object { "prop1": "y" }, I want it to be resolved as of #/definitions/b type, even if it's not really valid for this scheme. That is, I want to use just prop1 property for resolving.

I wonder if there is a way to do it using AJV custom keywords, without rebuilding the schema itself? In particular, if schema is not valid for an object, is it possible to use custom keywords to override it and make it valid?

1

There are 1 answers

5
esp On

If the objective is to only report errors from the correct schema you can use either "switch" (with v5 option, it is moved to ajv-keywords from version 5.0.0) or "if/then/else" (it is recommended as it is likely to be added in JSON Schema draft 7):

{
  "id": "schema",
  "if": { "properties": { "prop1": { "const": "x" } } },
  "then": { "$ref": "#/definitions/a" },
  "else": { "$ref": "#/definitions/b" }
}

If you need to know which schema was used for validation you can use a custom keyword to make a note of it:

{
  "id": "schema",
  "if": { "properties": { "prop1": { "const": "x" } } },
  "then": {
    "allOf": [
     { "schemaUsed": "schema#/definitions/a" },
     { "$ref": "#/definitions/a" }
    ]
  },
  "else": {
    "allOf": [
     { "schemaUsed": "schema#/definitions/b" },
     { "$ref": "#/definitions/b" }
    ]
  }
}

The keyword should be defined to store schema ID during validation in some variable so that after validation you could see which one was used.

If you need to get actual schema you can do:

var validate = ajv.getSchema('schema#/definitions/a'); // validating function
var schema = validate.schema; // schema as JSON