JSON Schema referencing in array items from another file

544 Views Asked by At

I have two JSON schemas - publisher and article, such that there could be multiple articles in a single publisher.

This is the article schema (in a.json):

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Article",
  "type": "object",
  "properties": {
    "aid": {
      "type": "integer"
    },
    "author": {
      "type": "string"
    },
    "title": {
      "type": "string"
    }
  },
  "required": ["aid", "author", "title"]
}

And I'm trying to reference this in publisher schema as below (in p.json, in the same dir):

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Publisher",
  "type": "object",
  "properties": {
    "pid": {
      "type": "integer"
    },
    "name": {
      "type": "integer"
    },
    "lang": {
      "type": "string"
    },
    "articles": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "object",
        "$ref": "./a.json"
      }
    }
  },
  "required": ["pid", "articles"]
}

I would ideally want the data to raise error if any of the articles do not have the required fields as mentioned in a.json. But this does not seem to happen:

import json, jsonschema

schema = json.load(open("p.json"))
data = {
  "pid": 1,
  "articles": [
    {
      "aid": 100,
      "title": "test",
    }
  ]
}
jsonschema.validate(data, schema)

The last line should raise an exception, as article does not have the author key that is marked as a requierd field in a.json.

But somehow, it raises _WrappedReferencingError: Unresolvable: ./a.json exception.

How can I reference a.json here such that it raise the correct exception?

2

There are 2 best solutions below

6
Jeremy Fiel On

The way you outlined your schemas is correct. Your error is the trailing comma on title. This is invalid JSON itself, not even JSON Schema.

1
Jason Desrosiers On

Some implementations understand filesystem references natively, but the implementation you're using doesn't. You need to configure it to map the p.json URI to your schema. I'm just going off of the documentation, but it looks like you would do something like this,

from referencing import Registry, Resource
from jsonschema import Draft202012Validator

article = json.load(open("a.json"))
publisher = json.load(open("p.json"))

registry = Registry().with_resources(
    [
        ("http://example.com/a.json", Resource.from_contents(article))
    ],
)

validator = Draft202012Validator(publisher, registry=registry)
validator.validate(data)

In addition, you'll need to add "$id": "http://example.com/p.json" to your p.json schema. That gives the implementation a base URI to use to resolve the a.json reference in the p.json schema. That makes the reference resolve to http://example.coma/a.json which matches a schema in the registry.