Python简单JSON解码器与复杂JSON问题
在我运行的一个单元测试中,我在下面的 JSON 文本的第四个对象上遇到了一个 KeyError
异常。这是因为负责解码的代码在寻找一个不存在的对象,但这个对象应该是有的。
我查看了子对象,发现是“cpuid”这个对象导致了问题。当我把它去掉后,测试就正常运行了。
def _make_report_entry(record):
response = self.app.post(
'/machinestats',
params = dict(record = self.json_encode([{
"type": "crash",
"instance_id": "xxx",
"version": "0.2.0",
"build_id": "unknown",
"crash_text": "Gah!"
},
{
"type": "machine_info",
"machine_info": "I'm awesome.",
"version": "0.2.0",
"build_id": "unknown",
"instance_id": "yyy"
},
{
"machine_info": "Soup",
"crash_text": "boom!",
"version": "0.2.0",
"build_id": "unknown",
"instance_id": "zzz",
"type": "crash"
},
{
"build_id": "unknown",
"cpu_brand": "intel",
"cpu_count": 4,
"cpuid": {
"00000000": {
"eax": 123,
"ebx": 456,
"ecx": 789,
"edx": 321
},
"00000001": {
"eax": 123,
"ebx": 456,
"ecx": 789,
"edx": 321
}
},
"driver_installed": True,
"instance_id": "yyy",
"version": "0.2.0",
"machine_info": "I'm awesome.",
"os_version": "linux",
"physical_memory_mib": 1024,
"product_loaded": True,
"type": "machine_info",
"virtualization_advertised": True
}
])))
在被测试的代码中,我使用了 django.utils 中的 simplejson.JSONDecoder 来解码 JSON。当我记录下传给我解码函数的 JSON 解码输出时,得到了这个:
root: INFO: {u'instance_id': u'xxx', u'type': u'crash', u'crash_text': u'Gah!', u'version': u'0.2.0', u'build_id': u'unknown'}
root: INFO: {u'build_id': u'unknown', u'instance_id': u'yyy', u'version': u'0.2.0', u'machine_info': u"I'm awesome.", u'type': u'machine_info'}
root: INFO: {u'build_id': u'unknown', u'machine_info': u'Soup', u'version': u'0.2.0', u'instance_id': u'zzz', u'crash_text': u'boom!', u'type': u'crash'}
root: INFO: {u'eax': 123, u'edx': 321, u'ebx': 456, u'ecx': 789}
在最后一个 JSON 对象中,只有 JSON 中的 cpuid 对象被传递给我的解码函数。因为我的解码函数期待其他对象(比如 'type'、'instance_id' 等),所以我得到了一个 KeyError 异常。
[抱歉之前的帖子太长了,希望这次能更简洁一些]
2 个回答
最后两行的错误信息:
File "...j_report/src/jreport/machinestats.py", line 77, in _make_report_entry
entry_type=record['type']
你现在有两个版本的def _make_report_entry(record):
注意,错误信息的前几行在说解码的问题,而不是编码。
第一个/原始版本和这个问题有什么关系呢?
你现在说:“因为我的解码函数期望其他对象(比如说'type'、'instance_id'等),所以我遇到了KeyError异常。”
所以可能你的解码函数被递归调用了,并且调用者希望它能处理任何结构,而不仅仅是包含'type'等的结构。
把你传给 self.json_encode
的内容复制粘贴,然后用它作为 json.dumps
的参数(在 Python 2.6 中需要先 import json
),这样做是没问题的。所以看起来可能是你没有展示的 json_encode
方法里有bug:除了调用 json.dumps
之外,它还做了什么呢...?(如果你用的是 Python 2.6 之前的版本,那就是 simplejson.dumps
了)。
编辑:使用 json_encode = json.JSONEncoder().encode
(就像提问者刚刚发的,虽然那是用的较老的 simplejson
,我之前提到过这个可能性)也是可以正常工作的。提问者在大编辑中附上的不完整堆栈跟踪信息表明,错误可能出现在 解码 的部分,可能是某个模型使用不当(具体情况不清楚,因为我们看不到模型)——提问者提到他现在提供了更多信息,但仍然不够来调试这个问题。
这强烈暗示提问者可以尝试逐步简化问题,直到最后一步简化后bug消失——这通常能很好地指示出bug可能在哪里。如果即使这样做也没有找到问题,提供一个最小的重现bug的方法,加上如果再删一点点代码bug就消失的信息,可能会帮助像我们这样的“第三方观察者”来协助调试。Stack Overflow 并不是专门为集体调试设计的平台(它更适合问答,这也是它最初的设计目的),但我认为用它来做这个不同的事情并不违反规则。