Generate python classes from JSON schema

23 Views Asked by At

I have one top-level schema content.json

{
    "title": "Program content schema",
    "$id": "https://example.com/schemas/program",
    "type": "object",
    "properties": {
        "content": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "string"
                },
                "tools": {
                    "$ref": "/schemas/tool"
                }
            }
        }
    }
}

which references another schema, tool.json

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Tool information schema",
    "$id": "https://example.com/schemas/tool",
    "allOf": [
        {
            "type": "object",
            "properties": {
                "nodeInformation": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string"
                        },
                        "description": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        {
            "$ref": "/schemas/gui"
        }
    ]
}

and that references another schema, gui.json

{
    "title": "Gui schema",
    "$id": "https://example.com/schemas/gui",
    "type": "object",
    "properties": {
      "active": {
            "type": "boolean"
        },
        "children": {
            "type": "array"
        }
    }
}

I used python-jsonschema-objects to generate python classes

resolver = RefResolver.from_schema(schema, store=schema_store)
self.validator = Draft7Validator(schema, resolver=resolver)

# Generate python classes
builder = pjs.ObjectBuilder(schema, )
ns = builder.build_classes()
print([str(x) for x in dir(ns)])

Only one class is build

['ProgramContentSchema']

How can I make it generate all the classes from the nested schema? Do I need to expand the referenced schema before I can generate the classes? If so, how can I expand them?

Edit 1: I tried datamodel-code-generator. If I pass gui.json then the generated model is as expected, but in case of tool.json or content.json, it is trying to resolve the references remotely I think. I also installed datamodel-code-generator[http], but the new error is

Traceback (most recent call last):
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/__main__.py", line 429, in main
    generate(
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/__init__.py", line 463, in generate
    results = parser.parse()
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/base.py", line 1149, in parse
    self.parse_raw()
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1703, in parse_raw
    self._parse_file(self.raw_obj, obj_name, path_parts)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1789, in _parse_file
    self.parse_obj(obj_name, root_obj, path_parts or ['#'])
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1664, in parse_obj
    self.parse_ref(obj, path)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1592, in parse_ref
    self.parse_ref(item, path)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1576, in parse_ref
    self.resolve_ref(obj.ref)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1566, in resolve_ref
    self._get_ref_body(relative_path),
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1517, in _get_ref_body
    return self._get_ref_body_from_url(resolved_ref)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1522, in _get_ref_body_from_url
    return self.remote_object_cache.get_or_put(
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/__init__.py", line 28, in get_or_put
    value = self[key] = default_factory(key)
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/parser/jsonschema.py", line 1523, in <lambda>
    ref, default_factory=lambda key: load_yaml(self._get_text_from_url(key))
  File "/home/user/venv/lib/python3.8/site-packages/datamodel_code_generator/__init__.py", line 51, in load_yaml
    return yaml.load(stream, Loader=SafeLoader)
  File "/home/user/venv/lib/python3.8/site-packages/yaml/__init__.py", line 81, in load
    return loader.get_single_data()
  File "/home/user/venv/lib/python3.8/site-packages/yaml/constructor.py", line 49, in get_single_data
    node = self.get_single_node()
  File "yaml/_yaml.pyx", line 673, in yaml._yaml.CParser.get_single_node
  File "yaml/_yaml.pyx", line 688, in yaml._yaml.CParser._compose_document
  File "yaml/_yaml.pyx", line 860, in yaml._yaml.CParser._parse_next_event
yaml.scanner.ScannerError: mapping values are not allowed in this context
  in "<unicode string>", line 13, column 15

Edit 2: I replaced

"$ref": "/schemas/tool"

with

"$ref": "tool.json"

and it works now. But jsonschema validation fails to resolve references. How can I make both happy?

Edit 3: I add '.json' while creating the schema store

schema_store = {schema["$id"] + '.json': schema for schema in schemas}

and it works now

0

There are 0 best solutions below