Python requests.json() 对象作为字典无法使用 hasattr() 或 object.keys() 调用中的值识别自己的键

sun*_*nny 2 python json dictionary mongodb

总结:dictionary/json 对象表示它没有给定的键(使用hasattr调用或value in object.keys布尔测试,即使该键出现在object.keys()调用中。那么我如何访问该键的值?

更长的版本:我很困惑试图解析一些从 API 返回的 json。当我尝试确定显示为字典的 json 对象是否具有给定的键时,即使代码显示该对象的键存在,该代码也会为该键返回 false。

这是我检索 json 的方法:

   r = requests.get(url, headers = {'User-Agent':UA})

    try:
        print(r.json())
        jsonobject = r.json()
        print("class of jsonobject is %s"%jsonobject.__class__.__name__)
        print("here are dictionary keys %s"%jsonobject.keys())
        if hasattr(jsonobject, 'laps') and jsonobject['laps'] is not None:
            ...
        else:
            print("no laps object")

        if hasattr(jsonobject, 'points') and jsonobject['points'] is not None:
           ...
Run Code Online (Sandbox Code Playgroud)

我这样做的原因是我经常从嵌套在 'laps' 数组或 'points' 数组中的字段中得到编码错误,因此我无法将 json 数据插入到 MongoDB 数据库中。我想从 json 对象中删除这些字段,因为它们无论如何都不包含有用的信息。

问题是 json 对象总是为 hasattr(jsonobject, 'laps') 和 hasattr(jsonobject,'points') 返回 false。即使在我打印出键的记录的情况下,它也返回 false,它们显示:

here are dictionary keys dict_keys(['is_peptalk_allowed', 'show_workout', 'hydration', 'records', 'include_in_stats', 'expand', 'pb_count', 'start_time', 'calories', 'altitude_max', 'hashtags', 'laps', 'pictures', 'duration', 'playlist'\
, 'sport', 'points', 'show_map', 'local_start_time', 'speed_avg', 'tagged_users', 'distance', 'altitude_min', 'is_live', 'author', 'feed_id', 'speed_max', 'id'])
Run Code Online (Sandbox Code Playgroud)

所以我想也许 dict 对 hasattr 的行为很奇怪,并将代码重写为:

if 'laps' in jsonobject.keys() and jsonobject['laps'] is not None:
Run Code Online (Sandbox Code Playgroud)

但这也会返回 false,即使再次命中也会打印包含“圈数”的相同键数组。

Mar*_*ers 5

hasattr()是完全错误的工具使用。它测试属性,但字典键不是属性。

要测试键,请直接对字典使用in测试:

if 'lap' in jsonobject:
Run Code Online (Sandbox Code Playgroud)

调用jsonobject.keys()是多余的,会创建一个新的字典视图对象。

这对您的词典来说是正确的,但这不是您要测试的唯一内容。你的测试是:

if 'lap' in jsonobject and jsonobject['lap'] is not None:
Run Code Online (Sandbox Code Playgroud)

如果'lap'是键但字典中的值为None.

上述测试可以更简单紧凑地表述为:

if jsonobject.get('lap') is not None:
Run Code Online (Sandbox Code Playgroud)

如果None是有效值,则不要对其进行测试;坚持只是'lap' in jsonobject