Search code examples
javascriptjsonschemaajv

How can I fix "Can't resolve reference" error when referencing an $id in the same document?


I want to validate a JSON against a JSON schema with Ajv in JavaScript. I get the error:

throw new it.MissingRefError(it.baseId, $schema, $message); ^ Error: can't resolve reference #/definitions/requestGraph from id requestGetGraphs

When removing reference to other schema: { "$ref" : "#/definitions/requestGraph" } the error disappears.

JavaScript-code:

ajv.addSchema(require('./json-schema/graph-response'), 'graph-response.json');
ajv.validate('requestGetGraphs', `{"type" : "requestGetGraphs", "space" : "config", "v" : 1.1, "id" : "dsaf" }`);

graph-request.json:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id" : "graph-requests.json",
  "definitions": {
    "requestGraph" : {
      "$id" : "#/definitions/requestGraph",
      "allOf" : [
        { "$ref" : "call.json/#/definitions/request" },
        {
          "properties": {
            "space": {
              "$id" : "#requestGraph/properties/space",
              "type": "string",
              "const": "config"
            }
          }
        }
      ]
    }
  },
  "requestGetGraphs" : {
      "$id" : "requestGetGraphs",
      "type" : "object",
      "allOf" : [
        {
          "properties": {
            "action": {
              "$id" : "#requestGetGraphs/properties/action",
              "type": "string",
              "const": "requestGetGraphs"
            }
          }
        },
        { "$ref" : "#/definitions/requestGraph" }
      ]

    }

}

Solution

  • This is to do with URI resolution. Check https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.2.2

    When an "$id" sets the base URI, the object containing that "$id" and all of its subschemas can be identified by using a JSON Pointer
    fragment starting from that location. This is true even of
    subschemas that further change the base URI. Therefore, a single
    subschema may be accessible by multiple URIs, each consisting of base URI declared in the subschema or a parent, along with a JSON Pointer
    fragment identifying the path from the schema object that declares
    the base to the subschema being identified. Examples of this are
    shown in section 8.2.4.

    Because you specified requestGetGraphs without a hash in front, it resolves as if a new schema (because it's not a fragment). Prefixing your $id with a hash signifies it's a fragment identifier, and URI resolution happens accordingly.

    You probably also meant to nest requestGetGraphs inside properties, right?