Python - 有一种优雅的方法可以避免数十个try / except块从json对象中获取数据吗?

时间:2011-07-27 02:00:00

标签: python json

我正在寻找编写像get_profile(js)这样的函数的方法,但没有所有丑陋的尝试/例外。

每个赋值都在try /中,因为偶尔json字段不存在。我很高兴有一个优雅的解决方案,即使我将一些默认值设置为None,也会将所有内容默认为[],如果这样做会使整个代码更好。

def get_profile(js):
    """ given a json object, return a dict of a subset of the data.
        what are some cleaner/terser ways to implement this?

        There will be many other get_foo(js), get_bar(js) functions which
        need to do the same general type of thing.
    """

    d = {}

    try:
        d['links'] = js['entry']['gd$feedLink']
    except:
        d['links'] = []

    try:
        d['statisitcs'] = js['entry']['yt$statistics']
    except:
        d['statistics'] = {}

    try:
        d['published'] = js['entry']['published']['$t']
    except:
        d['published'] = ''

    try:
        d['updated'] = js['entry']['updated']['$t']
    except:
        d['updated'] = ''

    try:
        d['age'] = js['entry']['yt$age']['$t']
    except:
        d['age'] = 0

    try:
        d['name'] = js['entry']['author'][0]['name']['$t']
    except:
        d['name'] = ''

    return d

5 个答案:

答案 0 :(得分:8)

  1. 使用dictionaries
  2. get(key[, default])方法
  3. 代码生成此样板代码,为您节省更多麻烦。

答案 1 :(得分:8)

使用字典get(key [,default])方法的链式调用替换每个try catch块。在链中最后一次调用之前获取的所有调用应该具有默认值{}(空字典),以便可以在有效对象上调用以后的调用,只有链中的最后一个调用应该具有默认值。你想要查找的关键。

请参阅python文档了解dictionairies http://docs.python.org/library/stdtypes.html#mapping-types-dict

例如:

d['links']     = js.get('entry', {}).get('gd$feedLink', [])
d['published'] = js.get('entry', {}).get('published',{}).get('$t', '')

答案 2 :(得分:3)

尝试类似......

import time

def get_profile(js):
    def cas(prev, el):
        if hasattr(prev, "get") and prev:
            return prev.get(el, prev)
        return prev
    def getget(default, *elements):
        return reduce(cas, elements[1:], js.get(elements[0], default))

    d = {}
    d['links'] = getget([], 'entry', 'gd$feedLink')
    d['statistics'] = getget({}, 'entry', 'yt$statistics')
    d['published'] = getget('', 'entry', 'published', '$t')
    d['updated'] = getget('', 'entry', 'updated', '$t')
    d['age'] = getget(0, 'entry', 'yt$age', '$t')
    d['name'] = getget('', 'entry', 'author', 0, 'name' '$t')
    return d

print get_profile({
    'entry':{
        'gd$feedLink':range(4),
        'yt$statistics':{'foo':1, 'bar':2},
        'published':{
            "$t":time.strftime("%x %X"),
        }, 
        'updated':{
            "$t":time.strftime("%x %X"),
        },
        'yt$age':{
            "$t":"infinity years",
        },
        'author':{0:{'name':{'$t':"I am a cow"}}},
    }
})

对我来说这是一种信念的飞跃,假设你有一个字典的密钥为0而不是列表但是......你明白了。

答案 3 :(得分:2)

您需要熟悉字典方法Check here,了解如何处理您所要求的内容。

答案 4 :(得分:1)

我们会想到两种可能的解决方案,而不了解您的数据结构的更多信息:

if k in js['entry']:
    something = js['entry'][k]

(虽然这个解决方案不会真正摆脱你的冗余问题,但它比一吨尝试/排除更简洁) 或

js['entry'].get(k, []) # or (k, None) depending on what you want to do

更短的版本就像...

for k,v in js['entry']:
    d[k] = v

但同样,关于你的数据还需要更多。