fuhrysteve/marshmallow-jsonschema

Extension for custom (enum) types?

carstencodes opened this issue · 3 comments

Hey there,

I'm using marshmallow in combination with data class extension by @lovasoa and the enum extension by @justanr to create a json schema from my data class.

Unfortunately, this does not work out of the box. The JSON Schema runs into errors when building the schema.

So I derived it to a EnumSupportingJSONSchema like this.

class _EnumSupportingJSONSchema(JSONSchema):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _get_python_type(self, field):
        if issubclass(field.__class__, EnumField):
            return field.enum

        return super(_EnumSupportingJSONSchema, self)._get_python_type(field)
    
    def _from_python_type(self, obj, field, pytype):
        if issubclass(field.__class__, EnumField):
            PY_TO_JSON_TYPES_MAP[pytype] = { "type" : "string" }
            PY_TO_JSON_TYPES_MAP[pytype]["enum"] = [ value.name for value in pytype ]
        return super(_EnumSupportingJSONSchema, self)._from_python_type(obj, field, pytype)

This works fine. Unfortunately the ruby-like part where I extend the singleton class looks crappy.

What I would like to suggest is to use a per-instance dictionary of maps, which is initialized from the global dictionaries.

This way, it would be possible to sub-class this this way:

class _EnumSupportingJSONSchema(JSONSchema):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _get_python_type(self, field):
        if issubclass(field.__class__, EnumField):
            enum_type = field.enum
            self.map(enum_type, { "type": "string", "enum": [ value.name for value in enum_type ] })
            return enum_type

        return super(_EnumSupportingJSONSchema, self)._get_python_type(field)

This way, the mapping would be only for the current instance and the JSONSchema is not "poisoned" by using optional values.

What do you think of my suggestion?

Please can I have enum support!

Please can I have enum support!

I think this is not that easy, since it adds a new dependency, which is also reflected to the python package. This can be avoided, if the enums would be declared as an extra.

My issue just was about enabling developers to create custom type mappings without modifying global configurations. Enums can be supplied using many different ways, the package I'm using is not the only possibility to create enum support.

On the other hand, please not, that the standard JSONEncoder in Python does not support enums as well an must be extended manually.

So, using Python enums is not that easy as it seems

kaos commented

This could be closed, now that #119 is merged.