将Python Enum编码为JSON
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了将Python Enum编码为JSON,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3596字,纯文字阅读大概需要6分钟。
内容图文
我有一个字典,其中一些键是Enum实例(enum.Enum的子类).我试图使用自定义JSON编码器类按照documentation将字典编码为JSON字符串.我想要的是让输出的JSON中的键是Enum名称的字符串.例如,{TestEnum.one:somevalue}将被编码为{“one”:somevalue}.
我写了一个简单的测试用例,如下所示,我在一个干净的virtualenv中测试过:
import json
from enum import Enum
class TestEnum(Enum):
one = "first"
two = "second"
three = "third"
class TestEncoder(json.JSONEncoder):
""" Custom encoder class """
def default(self, obj):
print("Default method called!")
if isinstance(obj, TestEnum):
print("Seen TestEnum!")
return obj.name
return json.JSONEncoder.default(self, obj)
def encode_enum(obj):
""" Custom encoder method """
if isinstance(obj, TestEnum):
return obj.name
else:
raise TypeError("Don't know how to decode this")
if __name__ == "__main__":
test = {TestEnum.one : "This",
TestEnum.two : "should",
TestEnum.three : "work!"}
# Test dumps with Encoder method
#print("Test with encoder method:")
#result = json.dumps(test, default=encode_enum)
#print(result)
# Test dumps with Encoder Class
print("Test with encoder class:")
result = json.dumps(test, cls=TestEncoder)
print(result)
我无法成功编码字典(使用Python 3.6.1).我不断得到TypeError:键必须是字符串错误,我的自定义编码器实例的默认方法(通过json.dumps方法的cls参数提供)似乎永远不会被调用?我还尝试通过json.dumps方法的默认参数提供自定义编码方法,但同样永远不会触发.
我见过涉及IntEnum类的解决方案,但我需要将Enum的值作为字符串.我还看过this answer,它讨论了一个与另一个类继承的Enum相关的问题.但是,我的枚举仅从基本的enum.Enum类继承并正确响应isinstance调用?
自定义类和方法在提供给json.dumps方法时都会产生TypeError.典型输出如下所示:
$python3 enum_test.py
Test with encoder class
Traceback (most recent call last):
File "enum_test.py", line 59, in <module>
result = json.dumps(test, cls=TestEncoder)
File "/usr/lib64/python3.6/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/usr/lib64/python3.6/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib64/python3.6/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
TypeError: keys must be a string
我认为问题是JSONEncoder类的encode方法假定它知道如何序列化Enum类(因为iterencode方法中的一个if语句被触发),所以从不调用自定义默认方法并结束无法序列化恩欧姆?
任何帮助将不胜感激!
解决方法:
您不能使用除字符串之外的任何内容作为要转换为JSON的词典中的键.编码器没有给你任何其他选择;默认钩子仅针对未知类型的值调用,永远不会针对键调用.
将您的密钥预先转换为字符串:
def convert_keys(obj, convert=str):
if isinstance(obj, list):
return [convert_keys(i, convert) for i in obj]
if not isinstance(obj, dict):
return obj
return {convert(k): convert_keys(v, convert) for k, v in obj.items()}
json.dumps(convert_keys(test))
这递归地处理您的字典键.请注意,我包括一个钩子;然后,您可以选择如何将枚举值转换为字符串:
def enum_names(key):
if isinstance(key, TestEnum):
return key.name
return str(key)
json.dumps(convert_keys(test, enum_names))
从JSON加载时,您可以使用相同的函数来反转进程:
def names_to_enum(key):
try:
return TestEnum[key]
except KeyError:
return key
convert_keys(json.loads(json_data), names_to_enum)
演示:
>>> def enum_names(key):
... if isinstance(key, TestEnum):
... return key.name
... return str(key)
...
>>> json_data = json.dumps(convert_keys(test, enum_names))
>>> json_data
'{"one": "This", "two": "should", "three": "work!"}'
>>> def names_to_enum(key):
... try:
... return TestEnum[key]
... except KeyError:
... return key
...
>>> convert_keys(json.loads(json_data), names_to_enum)
{<TestEnum.one: 'first'>: 'This', <TestEnum.two: 'second'>: 'should', <TestEnum.three: 'third'>: 'work!'}
内容总结
以上是互联网集市为您收集整理的将Python Enum编码为JSON全部内容,希望文章能够帮你解决将Python Enum编码为JSON所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。