Home > Net >  Importing `$defs` section from another schema?
Importing `$defs` section from another schema?

Time:06-28

Is it possible to import the entire $defs section from an external schema (using JSON Schema draft 2020)?

For example, let's say I have a set of three schemas like this:

"base"

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/schemas/base",
    "$defs": {
        "abc": {
            "type": "string",
            "pattern": "^[abcABC] $"
        }
    },
    "type": "object",
    "properties": {
        "baseprop1": {
             "title": "base property 1",
             "$ref": "#/$defs/abc"
        },
        "baseprop2": {
             "title": "base property 2",
             "$ref": "#/$defs/abc"
        }
    }
}

"better"

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/schemas/better",
    "$ref": "https://example.com/schemas/base",
    "type": "object",
    "properties": {
        "betterprop": {
             "title": "an additional, even better property!",
             "$ref": "base#/$defs/abc"
        }
    }
}

"best"

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/schemas/best",
    "$ref": "https://example.com/schemas/better",
    "type": "object",
    "properties": {
        "bestprop": {
             "title": "the best property!",
             "$ref": "base#/$defs/abc"
        }
    }
}

In base I've got $defs/abc defined. I can reference it in both the other schemas as base#/$defs/abc.

But what I'd like to do is somehow import its definition from base into better, so that in best I can reference it as better#/$defs/abc instead of base#/$defs/abc.

Is there a way to do this?

So far:

  • Using #/$defs/abc in best doesn't work; although I kind of actually expected it to, because I expected the top-level $ref to pull everything in to each schema, including the $defs object. (Similarily I noticed that #/$defs/abc doesn't work from better, either, even though I expected it to given the top-level $ref).

  • I tried this in better:

    "$defs": {
        "$ref": "base#/$defs"
    }
    

    But then AJV (at least) complains that $ref is not an object/bool (since it's a string). I hand-wavily tried "base#/$defs/" as well but that expectedly didn't work either.

  • I also tried this in better, again hand-waving:

    "$defs": {
        "allOf": [ { "$ref": "base#/$defs/" } ]
    }
    

    But again AJV complained (since it's an array).

I don't really have any other ideas.

Why isn't the $defs object being pulled in by the top-level $ref (even though e.g. the properties objects are being merged with no issue) and why isn't $ref working inside $defs? Is any of this possible? If so, how?

Also note that I say "import" but maybe there's some sort of "aliasing" type thing instead? My ultimate end goal is for all the things in base $defs to appear as if they're actually in better, from the POV of best. -- without explicitly just copy pasting them from base to better, of course.

CodePudding user response:

You can use the $id keyword to give your definitions a new name to use in references, so you don't have to keep track of whether it's defined in base or better:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/schemas/base",
    "$defs": {
        "abc": {
            "$id": "https://example.com/schemas/abc",
            "type": "string",
            "pattern": "^[abcABC] $"
        }
    },
...
}

https://json-schema.org/understanding-json-schema/structuring.html

  • Related