检查 JSON var 是否有可为空的键(Twitter Streaming API)

Check if JSON var has nullable key (Twitter Streaming API)

我正在使用 Tweepy 从 Twitter Streaming API 下载推文。我设法检查下载的数据是否具有 'extended_tweet' 的密钥,但我正在努力处理另一个密钥中的特定密钥。

def on_data(self, data):
    savingTweet = {}
        if not "retweeted_status" in data: 
            dataJson = json.loads(data)
            if 'extended_tweet' in dataJson:
                savingTweet['text'] = dataJson['extended_tweet']['full_text']
            else:
                savingTweet['text'] = dataJson['text']
            if 'coordinates' in dataJson:
                if 'coordinates' in dataJson['coordinates']:
                    savingTweet['coordinates'] = dataJson['coordinates']['coordinates']
            else:
                savingTweet['coordinates'] = 'null'

我正在正确地检查 'extended_key',但是当我尝试对 ['coordinates]['coordinates] 做同样的事情时,我收到以下错误:

TypeError: argument of type 'NoneType' is not iterable

Twitter 文档说密钥 'coordinates' 具有以下结构:

"coordinates":
{
    "coordinates":
    [
        -75.14310264,
        40.05701649
    ],
    "type":"Point"
}

我通过尝试将冲突检查放在一起来解决它,除了,但我认为这不是解决问题的最合适方法。还有其他想法吗?

所以 twitter API 文档可能在他们 return 的内容上撒了一些谎(令人震惊!)而且看起来你用 None 代替了预期的数据结构您已经决定不使用 try、catch,所以我不会再说了,但这里有一些其他建议。

默认使用dict get()

我想到了几个选项,第一个是利用 dict get 命令的默认功能。如果预期的密钥不存在,您可以提供回退,这允许您将多个调用链接在一起。

例如,您可以通过以下方式实现大部分您想要做的事情:

return {
    'text': data.get('extended_tweet', {}).get('full_text', data['text']),
    'coordinates': data.get('coordinates', {}).get('coordinates', 'null')
}

它不是很漂亮,但确实有效。您正在做的事情也可能会慢一些。

使用JSON路径

另一种选择,对于这种情况可能有点矫枉过正,是使用 JSONPath 库,它允许您在数据结构中搜索与查询匹配的项目。类似于:

from jsonpath_rw import parse

matches = parse('extended_tweet.full_text').find(data)
if matches:
    print(matches[0].value)

这会比您正在做的事情慢很多,而且对于少数几个领域来说是多余的,但如果您正在做大量此类工作,它可能是一个方便的工具。 JSONPath 还可以表达更复杂的路径,或者嵌套非常深的路径,其中 get 方法可能无法工作,或者会很笨拙。

先解析JSON!

我要提到的最后一件事是确保在对 "retweeted_status" 进行测试之前解析 JSON。如果文本出现在任何地方(比如推文的文本内部),就会触发此测试。

JSON 用有能力的库解析通常也非常快,所以除非你有真正的速度问题,否则不必担心。