Python简单JSON解码器与复杂JSON问题

0 投票
2 回答
598 浏览
提问于 2025-04-15 23:23

在我运行的一个单元测试中,我在下面的 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 个回答

0

最后两行的错误信息:

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'等的结构。

1

把你传给 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 并不是专门为集体调试设计的平台(它更适合问答,这也是它最初的设计目的),但我认为用它来做这个不同的事情并不违反规则。

撰写回答