I did review all the existing SO questions, googled around as best I could, tried a few different options, but can't seem to get what I want working.
Background
Simple problem - I've got a bunch of dataclasses in my code.
I'd like to have them all changed to inherit from the dataclasses-jsonschema
JsonSchemaMixin
so that I can programmatically generate a schema for them all.
Of course the simple approach is I could change all instances in the code everywhere to inherit from the JsonSchemaMixin
mixin.
But I was thinking I could also write my own decorator that would a) apply @dataclass, and b) mixin dataclasses-schema
in one go. ...my thinking being less chance of errors, and I could try writing a class decorator (I've only ever created and used my own function decorators)
# OLD
@dataclass
class X:
....
# Add the mixin `by hand` everywhere
@dataclass
class X(JsonSchemaMixin):
x: int
y: float
# What I want is to make my own decorator to do both:
@dataclass_mixedin
class X:
x: int
y: float
Problem
Pretty simple problem - I can't get this to work :(
What I've tried
try number 1:
from dataclasses import dataclass
from dataclasses_jsonschema import JsonSchemaMixin
def dc_schema(cls):
@dataclass
class _decorated(JsonSchemaMixin, cls):
pass
return _decorated
@dc_schema
class Data:
x: int
y: float
a = Data(x=5,y=1.1)
The above fails, with unexpected keyword args x & y.
Try number 2:
def dc_schema2(cls):
# Try applying dataclass() directly:
class _decorated(JsonSchemaMixin, cls):
pass
_decorated = dataclass(_decorated)
return _decorated
@dc_schema2
class Data2:
x: int
y: float
d = Data2(x=1, y=1.1)
Again - this fails with unexpected arguments.
So I'm guessing I'm missing dataclass
walking the class structure to find class variables with annotations (https://docs.python.org/3/library/dataclasses.html).
But I can't figure out how to do that
A possible solution is to use a metaclass. See this example:
I don't recommend this, because you need anyway to inherit from a base class and there is small difference in code verbosity. You lose useful features like type hints when coding with the help of MyPy (unless of writing a dedicated plugin), or Pylance, in an IDE that provides that kind of help.
I recommend to take into consideration
pydantic
: it might have the features you desire.