我正在尝试使用 Construct2.9 库序列化解析某些二进制数据的输出。我想将结果序列化为 JSON。
packet
是一个 Construct 类的实例 Container
。
显然它包含一个隐藏的 _io
类型 BytesIO
见下面的 dict(packet)
的输出:
{
'packet_length': 76, 'uart_sent_time': 1, 'frame_number': 42958,
'subframe_number': 0, 'checksum': 33157, '_io': <_io.BytesIO object at 0x7f81c3153728>,
'platform':661058, 'sync': 506660481457717506, 'frame_margin': 20642,
'num_tlvs': 1, 'track_process_time': 593, 'chirp_margin': 78,
'timestamp': 2586231182, 'version': 16908293
}
现在,调用 json.dumps(packet)
显然会导致类型错误:
...
File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <_io.BytesIO object at 0x7f81c3153728> is not JSON serializable
然而,令我感到困惑的是,运行 json.dumps(packet, skipkeys=True)
会导致完全相同的错误,而我希望它会跳过 _io
字段。这里有什么问题?为什么 skipkeys
不允许我跳过 _io
字段?
I got the code to work by JSONEncoder
and returning None
for fields of BytesIO
type, but that means my serialized string contains loads of "_io": null
元素,我根本不想拥有这些元素……
原文由 mz8i 发布,翻译遵循 CC BY-SA 4.0 许可协议
带有前导
_
下划线的键并不是真正的“隐藏”,它们只是 JSON 的更多字符串。 ConstructContainer
类只是一个带顺序的字典,_io
键对该类来说没有什么特别之处。你有两个选择:
default
钩子,它只返回一个替换值。也许是第三个,但是对 Construct 项目页面的随意扫描并没有告诉我它是否可用:具有 Construct 输出 JSON 或至少一个 JSON 兼容的字典,也许通过使用适配器。
默认挂钩无法阻止将
_io
键添加到输出中,但至少可以让您避免错误:可以递归地进行过滤;
@functools.singledispatch()
装饰器 可以帮助保持这样的代码干净:我在上面的实现中还有一个额外的
skip_underscore
参数,以显式跳过开头有_
字符的键。这将有助于跳过 Construct 库正在使用的所有其他“隐藏”属性。由于
Container
是dict
子类,以上代码将自动处理诸如packet
之类的实例。