为 class 创建装饰器以应用数据 class 和 JsonSchemaMixin ...不工作
Create decorator for class to apply dataclass and JsonSchemaMixin ...not working
我确实审查了所有现有的 SO 问题,尽我所能搜索,尝试了几个不同的选项,但似乎无法得到我想要的工作。
背景
简单问题 - 我的代码中有一堆数据class。
我想将它们全部更改为从 dataclasses-jsonschema
JsonSchemaMixin
继承,以便我可以通过编程方式为它们全部生成架构。
当然,简单的方法是我可以更改代码中所有实例以从 JsonSchemaMixin
mixin 继承。
但我在想我也可以编写自己的装饰器来 a) 应用@dataclass,以及 b) 一次性混合 dataclasses-schema
。 ...我的想法是错误的可能性较小,我可以尝试编写一个 class 装饰器(我只创建并使用过我自己的函数装饰器)
# 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
问题
非常简单的问题 - 我无法让它工作:(
我试过的
尝试编号 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)
以上失败,带有意外的关键字参数 x 和 y。
尝试数字 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)
再次 - 由于意外参数失败。
所以我猜我错过了 dataclass
遍历 class 结构来查找 class 带有注释的变量 (https://docs.python.org/3/library/dataclasses.html)。
但我不知道该怎么做
一个可能的解决方案是使用元class。
看这个例子:
from dataclasses import dataclass, is_dataclass
from dataclasses_jsonschema import JsonSchemaMixin
class EntityMeta(type):
def __new__(cls, name, bases, class_dict):
new_class = super().__new__(cls, name, bases, class_dict)
return dataclass()(new_class)
class BaseEntity(JsonSchemaMixin, metaclass=EntityMeta):
pass
class SomeClass(BaseEntity):
id: str
name: str
assert is_dataclass(SomeClass)
assert issubclass(SomeClass, JsonSchemaMixin)
x = SomeClass(1, "Hello World")
assert x.id == 1
assert x.name == "Hello World"
class SomeOtherClass(BaseEntity):
foo: str
name: str
x = SomeOtherClass("foo", "ufo")
assert x.foo == "foo"
assert x.name == "ufo"
print(SomeOtherClass.json_schema())
我不推荐这个,因为你
无论如何都需要从基础 class 继承,并且代码冗长程度差异很小。你失去了有用的功能,比如类型
在 MyPy(除非编写专用插件)或 Pylance 的帮助下进行编码时的提示,在 IDE 中提供此类帮助。
我建议考虑 pydantic
:它可能有您想要的功能。
我确实审查了所有现有的 SO 问题,尽我所能搜索,尝试了几个不同的选项,但似乎无法得到我想要的工作。
背景
简单问题 - 我的代码中有一堆数据class。
我想将它们全部更改为从 dataclasses-jsonschema
JsonSchemaMixin
继承,以便我可以通过编程方式为它们全部生成架构。
当然,简单的方法是我可以更改代码中所有实例以从 JsonSchemaMixin
mixin 继承。
但我在想我也可以编写自己的装饰器来 a) 应用@dataclass,以及 b) 一次性混合 dataclasses-schema
。 ...我的想法是错误的可能性较小,我可以尝试编写一个 class 装饰器(我只创建并使用过我自己的函数装饰器)
# 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
问题
非常简单的问题 - 我无法让它工作:(
我试过的
尝试编号 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)
以上失败,带有意外的关键字参数 x 和 y。
尝试数字 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)
再次 - 由于意外参数失败。
所以我猜我错过了 dataclass
遍历 class 结构来查找 class 带有注释的变量 (https://docs.python.org/3/library/dataclasses.html)。
但我不知道该怎么做
一个可能的解决方案是使用元class。 看这个例子:
from dataclasses import dataclass, is_dataclass
from dataclasses_jsonschema import JsonSchemaMixin
class EntityMeta(type):
def __new__(cls, name, bases, class_dict):
new_class = super().__new__(cls, name, bases, class_dict)
return dataclass()(new_class)
class BaseEntity(JsonSchemaMixin, metaclass=EntityMeta):
pass
class SomeClass(BaseEntity):
id: str
name: str
assert is_dataclass(SomeClass)
assert issubclass(SomeClass, JsonSchemaMixin)
x = SomeClass(1, "Hello World")
assert x.id == 1
assert x.name == "Hello World"
class SomeOtherClass(BaseEntity):
foo: str
name: str
x = SomeOtherClass("foo", "ufo")
assert x.foo == "foo"
assert x.name == "ufo"
print(SomeOtherClass.json_schema())
我不推荐这个,因为你 无论如何都需要从基础 class 继承,并且代码冗长程度差异很小。你失去了有用的功能,比如类型 在 MyPy(除非编写专用插件)或 Pylance 的帮助下进行编码时的提示,在 IDE 中提供此类帮助。
我建议考虑 pydantic
:它可能有您想要的功能。