Fully expanding $ref references in a json schema with Python
Asked Answered
N

3

7

We have a fairly large and complex json schema with many includes via $ref references. Ideally using Python and jsonschema I'd like to take those schema and fully expand the references (recursively) to get the full schema.

Output in the form of a dict is fine (the standard data structure that jsonschema uses to represent a schema).

Nestorius answered 1/11, 2017 at 11:46 Comment(1)
I don't think that it's possible to fully expand because $ref in json can have loopsArbuckle
A
4

If you check the json documentation.
You will find that circular $ref is not recommended but not prohibited. So, in this case, it is not possible to fully expand all $ref

But if you sure that you do not have loops in your $ref I would recommend you to use this repo It has helped me in such situation. Code is really simple so you can change it on your own.

Arbuckle answered 1/11, 2017 at 12:1 Comment(0)
F
4

I have tested and can also recommend the following module:

https://github.com/gazpachoking/jsonref

which is on PyPI. The documentation is good, has been very recently maintained (October 2018), and the syntax is such that it is a drop-in replacement for the standard json module:

from the home page:

>>> from pprint import pprint
>>> import jsonref

>>> # An example json document
>>> json_str = """{"real": [1, 2, 3, 4], "ref": {"$ref": "#/real"}}"""
>>> data = jsonref.loads(json_str)
>>> pprint(data)  # Reference is not evaluated until here
{'real': [1, 2, 3, 4], 'ref': [1, 2, 3, 4]}
Fruiter answered 12/11, 2018 at 15:37 Comment(1)
Unfortunately, there isn't an easy way to truly replace all the references into a native Python object (at least as far as I can tell). The $ref's are replaced by JsonRef objects, which helps when running pprint(), but that's not good enough for my purposes.Bullyrag
O
0

Here's a solution that is capable of expanding refs in the current document, even for refs to external JSON schema files which themselves may referecne other JSON schema files.

Using json.dumps() instead of print enables the JsonRef objects to be fully expanded upon output.

"""
Usage:
  json-schema-expand-refs.py <jsonfile>

Arguments:
  jsonfile   JSON schema file to have refs expanded

Options:
  -h --help     Show this screen.
  --version     Show version.
"""

from docopt import docopt
from jsonref import replace_refs
from pathlib import Path
import json


def load_json(file):
    with open(file, "r") as f:
        data = json.load(f)
    return data


if __name__ == "__main__":
    args = docopt(__doc__, version="0.1.0")
    jsonfile = args["<jsonfile>"]

    # replace_refs returns a copy of the document with refs replaced by JsonRef
    # objects.  It will resolve refences to other JSON schema files
    doc = replace_refs(
        load_json(jsonfile),
        merge_props=True,
        base_uri=Path(jsonfile).absolute().as_uri(),
    )
    print(json.dumps(doc, indent=2))
Olmsted answered 4/8, 2023 at 4:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.