s-knibbs / dataclasses-jsonschema

JSON schema generation from dataclasses
MIT License
166 stars 38 forks source link

Local Definitions #185

Open elael opened 2 years ago

elael commented 2 years ago

Greetings!

I'm proposing a new feature in this PR.

The Issue

We don't have control over the class whenever using an external library and thus need to use FieldEncoders. The issue arises when writing the FieldEncoder for a complex external object. Precisely when writing the JSON schema.

For example, when loading a protobuf object, one can parse using the ParseDict helper function. When it comes to defining the JSON schema, one would want to create something similar to this structure:

{
            "type": "object",
            "properties": {
                "ex_foo": {"$ref": "#/definitions/EX_FOO"},
                "ex_bar": {"$ref": "#/definitions/EX_BAR"},
            },
            "$schema": "http://json-schema.org/draft-06/schema#",
            "definitions": {
                "EX_FOO": {
                    "type": "object",
                    "properties": {
                        "ex_sub_foo": {
                            "type": "array",
                            "items": {"$ref": "#/definitions/EX_SUB_FOO"},
                        }
                    },
                },
                "EX_BAR": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                    },
                },
                "EX_SUB_FOO": {
                    "type": "object",
                    "properties": {"number": {"type": "integer"}},
                },
            },
        }

Where the definitions live in "definitions", but returning that in the FieldEncoder would give errors as:

jsonschema.exceptions.RefResolutionError: Unresolvable JSON pointer: 'definitions/EX_FOO'

Solution

These errors happen because when compiling the JSON schema for an internal JsonSchemaMixin sub-class we don't propagate the "definitions" created using the FieldEncoder.

This way I propose handling this as another case on the _get_field_definitions method.