如何将 IntEnum 从 enum34 序列化为 json in python?
How do I serialize IntEnum from enum34 to json in python?
我正在使用 enum34 包并设法以自定义格式将对象子类化存储到 json。但是,我有一个对象实例使用了很多,它是 IntEnum 的子类,我的自定义 JSONEncoder 似乎没有正确拾取它。
我最后的办法是将其转换为枚举并相应地重构所有相关代码。 IntEnum 的优点是我可以按位 operations/tests.
以下是示例和自定义编码器。请注意,Enum 有效,但我认为 IntEnum 在传递给默认函数之前已被捕获。
class TimeMode(Enum):
NTSC = 0
PAL = 1
Film = 2
class UiFlags(IntEnum):
Empty = 0
Clear = 0
Checked = 1
Selected = 2
Shared = 8
class CObjectsEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, IntEnum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
if isinstance(o, Enum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
return json.JSONEncoder.default(self, o)
time_mode = TimeMode.NTSC
ui_flags = UiFlags.Checked
CObjectsEncoder().encode(time_mode)
CObjectsEncoder().encode(ui_flags)
结果:
'{"__class__": "TimeMode", "__value__": [0]}' # correct encoding
'UiFlags.Checked' # incorrect encoding
有什么方法可以让 IntEnum 得到相同的结果?我假设它像 int 一样被预先转换为 str。如何让编码器接收 IntEnum?
这里的问题是 isinstance(ui_flags, int)
是真的,这意味着使用了整数的 标准 编码。您的自定义编码器永远不会被调用,因为内置编码器 'knows' 如何处理整数:
>>> isinstance(UiFlags.Checked, IntEnum)
True
>>> isinstance(UiFlags.Checked, int)
True
JSONEncoder
级别有解决方法;你可以预处理你的结构:
def map_intenum(data):
if isinstance(data, IntEnum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
if isinstance(data, dict):
return {k: map_intenum(v) for k, v in data.iteritems()}
if isinstance(data, (list, tuple)):
return [map_intenum(v) for v in data]
return data
并将其应用到您的待编码数据 之前 编码为 JSON:
json.dumps(map_intenum(data), cls=CObjectsEncoder)
下一步将覆盖 JSONEncoder.iterencode()
并在编码前应用转换:
class CObjectsEncoder(json.JSONEncoder):
def iterencode(self, o, _one_shot=False):
o = map_intenum(o)
return super(CObjectsEncoder, self).iterencode(o, _one_shot)
def default(self, o):
if isinstance(o, Enum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
return super(CObjectsEncoder, self).default(o)
我通过在我的 IntEnum class:
上实现 __str__
来解决这个问题
class UiFlags(IntEnum):
Empty = 0
Clear = 0
def __str__(self):
return str(self.value)
json.dumps({'empty': UiFlags.Empty, 'clear': UiFlags.Clear})
# {"empty": 0, "clear": 1}
我正在使用 enum34 包并设法以自定义格式将对象子类化存储到 json。但是,我有一个对象实例使用了很多,它是 IntEnum 的子类,我的自定义 JSONEncoder 似乎没有正确拾取它。
我最后的办法是将其转换为枚举并相应地重构所有相关代码。 IntEnum 的优点是我可以按位 operations/tests.
以下是示例和自定义编码器。请注意,Enum 有效,但我认为 IntEnum 在传递给默认函数之前已被捕获。
class TimeMode(Enum):
NTSC = 0
PAL = 1
Film = 2
class UiFlags(IntEnum):
Empty = 0
Clear = 0
Checked = 1
Selected = 2
Shared = 8
class CObjectsEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, IntEnum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
if isinstance(o, Enum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
return json.JSONEncoder.default(self, o)
time_mode = TimeMode.NTSC
ui_flags = UiFlags.Checked
CObjectsEncoder().encode(time_mode)
CObjectsEncoder().encode(ui_flags)
结果:
'{"__class__": "TimeMode", "__value__": [0]}' # correct encoding
'UiFlags.Checked' # incorrect encoding
有什么方法可以让 IntEnum 得到相同的结果?我假设它像 int 一样被预先转换为 str。如何让编码器接收 IntEnum?
这里的问题是 isinstance(ui_flags, int)
是真的,这意味着使用了整数的 标准 编码。您的自定义编码器永远不会被调用,因为内置编码器 'knows' 如何处理整数:
>>> isinstance(UiFlags.Checked, IntEnum)
True
>>> isinstance(UiFlags.Checked, int)
True
JSONEncoder
级别有解决方法;你可以预处理你的结构:
def map_intenum(data):
if isinstance(data, IntEnum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
if isinstance(data, dict):
return {k: map_intenum(v) for k, v in data.iteritems()}
if isinstance(data, (list, tuple)):
return [map_intenum(v) for v in data]
return data
并将其应用到您的待编码数据 之前 编码为 JSON:
json.dumps(map_intenum(data), cls=CObjectsEncoder)
下一步将覆盖 JSONEncoder.iterencode()
并在编码前应用转换:
class CObjectsEncoder(json.JSONEncoder):
def iterencode(self, o, _one_shot=False):
o = map_intenum(o)
return super(CObjectsEncoder, self).iterencode(o, _one_shot)
def default(self, o):
if isinstance(o, Enum):
return {'__class__': o.__class__.__name__,
'__value__': (o.value,)}
return super(CObjectsEncoder, self).default(o)
我通过在我的 IntEnum class:
上实现__str__
来解决这个问题
class UiFlags(IntEnum):
Empty = 0
Clear = 0
def __str__(self):
return str(self.value)
json.dumps({'empty': UiFlags.Empty, 'clear': UiFlags.Clear})
# {"empty": 0, "clear": 1}