I'd like to reuse object properties in Ajv schema, but it claims that some part cannot be resolved:
const Ajv = require("ajv@8.11.0").default
const ajv = new Ajv({
strictSchema: false,
loadSchema: async (uri) => {
console.log(uri);
switch (uri) {
case "main":
return {
entity: { $ref: "entity" },
request: { $ref: "request" }
}
case "entity":
return {
type: "object",
properties: {
id: {type: "string"}
},
}
case "request":
return {
type: "object",
properties: {
id: {$ref: "main#/entity/properties/id"}
},
}
}
},
})
const validate = await ajv.compileAsync({
$ref: "main#/request"
})
validate({
id: "123"
})
produces error: Error: AnySchema main is loaded but main#/entity/properties/id cannot be resolved
while replacing main#/entity/properties/id
with entity#/properties/id
makes it work. What I am missing?
Live code: https://runkit.com/desofto/64a40e034daec80008a495b5
Your main
schema is precisely this:
{
entity: { $ref: "entity" },
request: { $ref: "request" }
}
The JSON Pointer #/entity/properties/id
doesn't resolve to a location within main
.
It looks like you're expecting the JSON Pointer to resolve the { $ref: "entity" }
at main#/entity
, but JSON Pointers don't resolve references.
The code you posted may just be an example to illustrate your point, but given that entity#/properties/id
is just
{ "type": "string" }
it may just make more sense to repeat that in your request
object rather than trying to reference into entity
to get it. Typically references don't extract subschemas that way. They can, but it's not advised to do so.
If you'd really like to reference it, I suggest you extract that out into a new schema and reference it from both places.
Another option is to compose all of these into a single schema and make use of $defs
to house any reusable pieces.