为什么我的JSON数据中的null不返回0而引发异常?

huangapple go评论65阅读模式
英文:

Why is my JSON data with null not returning 0 causing an exception?

问题

我有一个API,当没有结果时返回null,否则通常返回一个int类型的计数。在这个类似数据结构的最小示例中,如果其中一个值为null,我希望返回0。

我以为添加{}通常可以深入遍历我得到的数据,但我得到以下错误:

追踪(最近一次调用在最上面) 文件
"/home/Documents/projects/data-reviews/test_code.py",第52行,在

total_reviews = data.get('data', {}).get('node', {}).get('reviews', {}).get('aggregates', {}).get('count', {})
AttributeError: 'NoneType' 对象没有属性 'get'

我不知道在这里该怎么做,尝试使用try: except:是唯一的选择吗?

import json

resp = """{
    "data": {
        "node": {
            "myReviews": {
                "totalReviews": 0
            },
            "allReviews": {
                "aggregates": null
            }
        }
    }
}"""

data = json.loads(resp)

total_ratings = data.get('data', {}).get('node', {}).get('myReviews', {}).get('totalReviews', 0)
total_reviews = data.get('data', {}).get('node', {}).get('allReviews', {}).get('aggregates', {}).get('count', 0)
英文:

I have an API which returns null when there are no results, else it's usually got a count with an int. In this minimal example with a similar data structure, if either value is null I'd hope to return 0.

I thought that adding {} usually allows traversing deeper into the data I get the following:

> Traceback (most recent call last): File
> "/home/Documents/projects/data-reviews/test_code.py", line 52, in
> <module>
> total_reviews = data.get('data', {}).get('node', {}).get('reviews', {}).get('aggregates', {}).get('count', {})
> AttributeError: 'NoneType' object has no attribute 'get'

I'm not what to do here or it try: except: the only option?

import json

resp = &quot;&quot;&quot;{
    &quot;data&quot;: {
        &quot;node&quot;: {
            &quot;myReviews&quot;: {
                &quot;totalReviews&quot;: 0
            },
            &quot;allReviews&quot;: {
                &quot;aggregates&quot;: null
            }
        }
    }
}&quot;&quot;&quot;

data = json.loads(resp)

total_ratings = data.get(&#39;data&#39;, {}).get(&#39;node&#39;, {}).get(&#39;myReviews&#39;, {}).get(&#39;totalReviews&#39;, 0)
total_reviews = data.get(&#39;data&#39;, {}).get(&#39;node&#39;, {}).get(&#39;allReviews&#39;, {}).get(&#39;aggregates&#39;, {}).get(&#39;count&#39;, 0)

答案1

得分: 3

get方法的fallback参数仅在值未定义时才会被使用。如果get显式返回None,那就是结果。

就像你写的一样,常见的解决方法是使用try/except

try:
    total_ratings = data['data']['node']['myReviews']['totalReviews']
except KeyError:
    total_ratings = 0
try:
    total_reviews = data['data']['node']['allReviews']['aggregates']['count']
except KeyError:
    total_reviews = 0
英文:

The fallback argument of the get method only gets used if the value is not defined. If get explicitly returns None then that is the result.

Like you write, the common workaround is to use try/except:

try:
    total_ratings = data[&#39;data&#39;][&#39;node&#39;][&#39;myReviews&#39;][&#39;totalReviews&#39;]
except KeyError:
    total_ratings = 0
try:
    total_reviews = data[&#39;data&#39;][&#39;node&#39;][&#39;allReviews&#39;][&#39;aggregates&#39;][&#39;count&#39;]
except KeyError:
    total_reviews = 0

答案2

得分: 0

You can use the optional object_hook function to replace the null value.

import json

def as_null(resp):
    if "aggregates" in resp and resp["aggregates"] is None:
        print(resp)
        resp["aggregates"] = {'count': 0}
        print(resp)
    return resp

resp = """{
    "data": {
        "node": {
            "myReviews": {
                "totalReviews": 0
                
                
            },
            "allReviews": {
                "aggregates": null
            }
        }
    }
}"""

data = json.loads(resp, object_hook=as_null)
total_ratings = data.get('data', {}).get('node', {}).get('myReviews', {}).get('aggregates', {}).get('count', 0)
total_reviews = data.get('data', {}).get('node', {}).get('allReviews', {}).get('aggregates', {}).get('count', 0)
print(data)
print(total_ratings, total_ratings)

Or use it to immediately get the count values you need.

英文:

You can use the optional object_hook function to replace the null value.

import json


def as_null(resp):
    if &quot;aggregates&quot; in resp and resp[&quot;aggregates&quot;] is None:
        print(resp)
        resp[&quot;aggregates&quot;] = {&#39;count&#39;: 0}
        print(resp)
    return resp


resp = &quot;&quot;&quot;{
    &quot;data&quot;: {
        &quot;node&quot;: {
            &quot;myReviews&quot;: {
                &quot;totalReviews&quot;: 0
                
                
            },
            &quot;allReviews&quot;: {
                &quot;aggregates&quot;: null
            }
        }
    }
}&quot;&quot;&quot;

data = json.loads(resp, object_hook=as_null)
total_ratings = data.get(&#39;data&#39;, {}).get(&#39;node&#39;, {}).get(&#39;myReviews&#39;, {}).get(&#39;aggregates&#39;, {}).get(&#39;count&#39;, 0)
total_reviews = data.get(&#39;data&#39;, {}).get(&#39;node&#39;, {}).get(&#39;allReviews&#39;, {}).get(&#39;aggregates&#39;, {}).get(&#39;count&#39;, 0)
print(data)
print(total_ratings, total_ratings)

----------------------

{&#39;aggregates&#39;: None}
{&#39;aggregates&#39;: {&#39;count&#39;: 0}}
{&#39;data&#39;: {&#39;node&#39;: {&#39;myReviews&#39;: {&#39;totalReviews&#39;: 0}, &#39;allReviews&#39;: {&#39;aggregates&#39;: {&#39;count&#39;: 0}}}}}
0 0

Or use it to immediately get the count values you need.

huangapple
  • 本文由 发表于 2023年5月6日 18:16:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76188348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定