Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension for custom (enum) types? #110

Closed
carstencodes opened this issue Mar 22, 2020 · 3 comments
Closed

Extension for custom (enum) types? #110

carstencodes opened this issue Mar 22, 2020 · 3 comments

Comments

@carstencodes
Copy link

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?

@michaelwiles
Copy link

Please can I have enum support!

@carstencodes
Copy link
Author

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
Copy link
Contributor

kaos commented Mar 23, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants