【问题标题】:Parsing JSON with python: blank fields用python解析JSON:空白字段
【发布时间】:2013-05-05 17:31:37
【问题描述】:

我在使用 python 解析 JSON 时遇到问题,现在我被卡住了。
问题是我的 JSON 的实体并不总是相同的。 JSON 类似于:

"entries":[
{
"summary": "here is the sunnary",
"extensions": {
   "coordinates":"coords",
   "address":"address",
   "name":"name"
   "telephone":"123123"
   "url":"www.blablablah"
},
}
]

我可以在 JSON 中移动,例如:

for entrie in entries:
  name =entrie['extensions']['name']
  tel=entrie['extensions']['telephone']

问题来了,因为有时,JSON 没有所有“字段”,例如,telephone 字段,有时缺少,所以,脚本失败 KeyError,因为键 电话此条目中缺少
所以,我的问题是:我怎么能运行这个脚本,在 telephone 丢失的地方留下一个空白? 我试过了:

if entrie['extensions']['telephone']:
    tel=entrie['extensions']['telephone']

但我觉得不行。

【问题讨论】:

    标签: python json parsing python-2.7


    【解决方案1】:

    使用dict.get 代替[]

    entries['extensions'].get('telephone', '')
    

    或者,简单地说:

    entries['extensions'].get('telephone')
    

    get 将返回第二个参数(默认为 None),而不是在找不到密钥时引发 KeyError

    【讨论】:

      【解决方案2】:

      如果数据只有一处缺失,那么可以用dict.get来补缺:

      tel = d['entries'][0]['extensions'].get('telelphone', '')
      

      如果问题更为普遍,您可以让 JSON 解析器使用 defaultdict 或自定义字典而不是常规字典。例如,给定 JSON 字符串:

      json_txt = '''{
          "entries": [
              {
                  "extensions": {
                      "telephone": "123123", 
                      "url": "www.blablablah", 
                      "name": "name", 
                      "coordinates": "coords", 
                      "address": "address"
                  }, 
                  "summary": "here is the summary"
              }
          ]
      }'''
      

      解析它:

      >>> class BlankDict(dict):
              def __missing__(self, key):
                  return ''
      
      >>> d = json.loads(json_txt, object_hook=BlankDict)
      
      >>> d['entries'][0]['summary']
      u'here is the summary'
      
      >>> d['entries'][0]['extensions']['color']
      ''
      

      附带说明,如果您想清理数据集并强制保持一致性,有一个名为 Kwalify 的好工具可以对 JSON(和 YAML)进行架构验证;

      【讨论】:

      • 很好,我比defaultdict 更喜欢这个,因为在__missing__ 方法中可以添加一些逻辑来捕获潜在的错误。对于defaultdict,我总是畏缩,因为当我打错字时不会收到 KeyError。
      • entries['extensions'].get('telephone', {}).get('anothermissingkey',{}) 几乎是 object_hook=BlankDict 方法的 3 倍(在 Deb9 的 py3.5 上),它适用于多个级别
      【解决方案3】:

      您可以使用几个有用的字典功能来处理它。

      首先,您可以使用in 来测试字典中是否存在键:

      if 'telephone' in entrie['extensions']:
          tel=entrie['extensions']['telephone']
      

      get 也可能有用;如果缺少键,它允许您指定默认值:

      tel=entrie['extensions'].get('telephone', '')
      

      除此之外,您可以查看标准库的 collections.defaultdict,但这可能有点过头了。

      【讨论】:

        【解决方案4】:

        两种方式。

        一个是确保您的字典是标准的,并且当您阅读它们时,它们包含所有字段。另一个是访问字典时要小心。

        这是一个确保您的字典是标准的示例:

        __reference_extensions = {
           # fill in with all standard keys
           # use some default value to go with each key
           "coordinates" : '',
           "address" : '',
           "name" : '',
           "telephone" : '',
           "url" : ''
        }
        
        entrie = json.loads(input_string)
        d = entrie["extensions"]
        for key, value in __reference_extensions:
            if key not in d:
                d[key] = value
        

        以下是访问字典时要小心的示例:

        for entrie in entries:
           name = entrie['extensions'].get('name', '')
           tel = entrie['extensions'].get('telephone', '')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多