0
votes

Good morning, I have a problem using ajv with a json-schema, when using a $ref to something defined in the same json file. I suspect that the problem is with the use of ids, I would understand more about that.

My files are:

definitions.json

{
    "$schema":"http://json-schema.org/draft-06/schema#",
    "definitions": {
        "person":{
            "$schema":"http://json-schema.org/draft-06/schema#",
            "$id": "http://asite.org/schemas/person.json",
            "type":"object",
            "properties": {
                "name":{"type":"string"},
                "surname":{"type":"string"},
                "email": {"type": "string", "format": "email"},
                "sex":{"$ref": "types.json#/definitions/gender"}},
            "required":["name", "surname", "sex", "email"]
        },
        "member":{
            "$schema":"http://json-schema.org/draft-06/schema#",
            "type": "object",
            "$id": "http://asite.org/schemas/member.json",
            "allOf":[
                {"$ref": "#/definitions/person"},
                {
                    "properties": {
                        "id":{"type":"integer"},
                        "role":{"$ref": "types.json#/properties/man_role"},
                        "is_expert":{"type":"boolean", "default":false},
                        "is_board":{"type":"boolean", "default": false}
                    }
                }
            ]
        }
    },
    "type":"object",
    "properties": {
        "person": {"$ref": "#/definitions/person"},
        "member": {"$ref": "#/definitions/member"}
    }
}

types.json

{
    "$schema":"http://json-schema.org/draft-06/schema#",
    "$id": "http://asite.org/schemas/types.json",
    "type": "object",
    "definitions": {
        "gender":{"enum": ["male", "female"]},
        "man_role":{"enum": ["admin", "supervisor", "clerk", "none"]}
    },
    "properties":{
        "gender":{"$ref": "#/definitions/gender"},
        "man_role": {"$ref": "#/definitions/man_role"}
    }
}

I looked at this question, but I didn't figure it out how to correct my example. The error I get is:

MissingRefError: can't resolve reference #/definitions/person from id http://asite.org/schemas/member.json

The references work if I try with VisualStudio Code, e.g I can create a "member" and it recognizes also the properties of "person".

Can anyone tell me how should write these schemas to make them work with ajv?

The code that generates the error is:

import Ajv, {JSONSchemaType, DefinedError} from "ajv"
import {Person, Member} from "./definitions";
import addFormats from "ajv-formats"

const ajv = new Ajv();
addFormats(ajv);
ajv.addMetaSchema(require("../node_modules/ajv/lib/refs/json-schema-draft-06.json"))

const types = require("../types.json");
const PersonSchema : JSONSchemaType<Person> = require('../definitions.json').definitions.person;
const MemberSchema: JSONSchemaType<Member> = require('../definitions.json').definitions.member;
ajv.addSchema(types);

const isPerson = ajv.compile(PersonSchema);
const isMember = ajv.compile(MemberSchema)
//other stuff, use of isPerson and isMember on example objects

1

1 Answers

1
votes

Your intuition is correct, the $ref isn't resolving as you expect because of the $id. $refs are resolved against the $id of the schema. In this case, { "$ref": "#/definitions/person" } is resolved against "$id": "http://asite.org/schemas/member.json" resulting in http://asite.org/schemas/member.json#/definitions/person which doesn't exist. The solution is to use the $id of the person schema rather than a relative path: { "$ref": "person.json" }.


As an aside, you might prefer the alternate API for compiling schemas that works better when dealing with bundled schemas like your "definitions.json". You can load the whole file and then compile the individual schemas you want by their $id.

const ajv = new Ajv();
ajv.addMetaSchema(draft06);
ajv.addSchema(definitions);
ajv.addSchema(types);
const isPerson = ajv.getSchema("http://asite.org/schemas/person.json");
const isMember = ajv.getSchema("http://asite.org/schemas/member.json");