unl*_*fox 7 python enums serialization json-deserialization python-attrs
我想创建一个类,它有一个枚举作为属性。此枚举应具有字符串表示形式,在将使用枚举属性的类实例转储为 JSON 字符串时,该表示形式显示为人类可读的值。在下面的最小工作示例中,我以三种不同的方式创建了三个枚举。
反序列化后,每个属性都向我们表明它来自枚举,但带有字符串表示形式的枚举除外。它只是一个字符串。
如果不可能实现这样的结构,我想知道为什么。
如果你想测试它,你必须安装jsons并attrs使用
pip install attrs jsons
Run Code Online (Sandbox Code Playgroud)
在这里您可以看到一个最小的工作示例。
import jsons
import attr
from enum import Enum
# ----------------------------------------------------
# create enumeration with the help of a dictionary
fruits = {
"PINEAPPLE": "PINEAPPLE",
"APPLE": "APPLE",
"ORANGE": "ORANGE",
"BANANA": "BANANA",
}
Fruit = Enum("FRUITS", fruits)
# ----------------------------------------------------
# create a classical enumeration
class Nut(Enum):
PEANUT = 1
HAZELNUT = 2
CASHEW = 3
WALNUT = 4
# ----------------------------------------------------
# create enumeration with a string representation
class Vegetable(str, Enum):
BROCCOLI = "BROCCOLI"
CUCUMBER = "CUCUMBER"
POTATO = "POTATO"
ONION = "ONION"
# ----------------------------------------------------
# create a class which uses the enumerations
@attr.s(auto_attribs=True, kw_only=True)
class Order(jsons.JsonSerializable):
fruit: Fruit
nut: Nut
vegetable: Vegetable
# ----------------------------------------------------
# initialize an order object, serialize and deserialize it
order = Order(fruit=Fruit.APPLE, nut=Nut.PEANUT, vegetable=Vegetable.CUCUMBER)
json_string: str = Order.dumps(order)
order_deserialised: Order = Order.loads(json_string)
Run Code Online (Sandbox Code Playgroud)
order和变量的结构order_deserialised:
order: Order(fruit=<FRUITS.APPLE: 'APPLE'>, nut=<Nut.PEANUT: 1>, vegetable=<Vegetable.CUCUMBER: 'CUCUMBER'>)
order_deserialised: Order(fruit=<FRUITS.APPLE: 'APPLE'>, nut=<Nut.PEANUT: 1>, vegetable='CUCUMBER')
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,将order_deserialised蔬菜显示为字符串而不是枚举。
也许你已经知道这一点,但我是为未来的读者回答的。
此问题已在 JSONS 1.6.1 中修复,如以下示例所示。
import enum
import jsons
class Vegetable(str, enum.Enum):
BROCCOLI = "BROCCOLI"
print(jsons.loads(jsons.dumps(Vegetable.BROCCOLI), Vegetable))
# This will output "Vegetable.BROCCOLI" with JSONS 1.6.1 or later
Run Code Online (Sandbox Code Playgroud)
class Vegetable(str, Enum)与其他人对这个问题的评论不同,派生一个类似的类是完全可以的。Python 3.11中添加了类似的想法StrEnum。