我正在尝试解析JSON数据,但是当我在JSON的某些分支中具有NULL时,Python会给我一个错误:
TypeError: 'NoneType' object is not subscriptable
。
这种情况还可以:
import json
x = '''[{"address":{"city": "city1","street": "street1"}},
{"address":{"city": "city2","street": "street2"}}]'''
source = json.loads(x)
data = []
for s in source:
data.append([s['address']['city'],
s['address']['street']])
print(data)
这给了我一个错误:
import json
x = '''[{"address":{"city": "city1","street": "street1"}},
{"address": null},
{"address":{"city": "city2","street": "street2"}}]'''
source = json.loads(x)
data = []
for s in source:
data.append([s['address']['city'],
s['address']['street']])
print(data)
我想在第二种情况下获得NULL(无)值。最简单的方法是什么?
更新#1:
我还有很多其他数据,不仅是“地址”,而且其中任何一个也可以为NULL。这就是为什么我不能使用“ if
语句”的原因(会有太多不同的组合)
更新#2: 为了使我的问题更清楚(实际上,我有25个不同的参数,而不是下面的3个):
[
{
"address": {
"city": "city1",
"street": "street1"
},
"car": null,
"person": {
"age": "30",
"name": "John"
}
},
{
"address": null,
"car": {
"color": "red",
"year": "2015"
},
"person": {
"age": "31",
"name": "Peter"
}
},
{
"address": {
"city": "city2",
"street": "street2"
},
"car": {
"color": "green",
"year": "2017"
},
"person": null
}
]
data.append( [s['address']['city'],
s['address']['street'],
s['person']['name'],
s['paerson']['age'],
s['car']['year'],
s['car']['color']])
答案 0 :(得分:2)
当您将JSON对象嵌套在一级深度且可能具有NULL值的情况下,这是一种处理情况的通用方法。它利用可选的object_hook=
关键字参数将回调函数传递给json.loads()
(与json.load()
一样)。在这种情况下,函数会将上层None
中的任何dict
值转换为空的NoneDict
字典子类实例。
NoneDict
只需返回None
作为丢失键的值,而不用引发KeyError
。优化说明:如果您从不更改这些对象(即它们是只读的),则实际上只需要创建一个单独的全局实例,并始终在convertor()
函数中使用它即可。
import json
from pprint import pprint
class NoneDict(dict):
""" dict subclass that returns a value of None for missing keys instead
of raising a KeyError. Note: doesn't add item to dictionary.
"""
def __missing__(self, key):
return None
def converter(decoded_dict):
""" Convert any None values in decoded dict into empty NoneDict's. """
return {k: NoneDict() if v is None else v for k,v in decoded_dict.items()}
# The following JSON data is equivalent to what you have in Update #2 of your
# question, it's just formatted more compactly.
x = '''
[{"address": {"city": "city1", "street": "street1"},
"car": null,
"person": {"age": "30", "name": "John"}},
{"address": null,
"car": {"color": "red", "year": "2015"},
"person": {"age": "31", "name": "Peter"}},
{"address": {"city": "city2", "street": "street2"},
"car": {"color": "green", "year": "2017"},
"person": null}]
'''
source = json.loads(x, object_hook=converter)
data = []
for s in source:
data.append([s['address']['city'],
s['address']['street'],
s['person']['name'],
s['person']['age'],
s['car']['year'],
s['car']['color']])
pprint(data)
输出:
[['city1', 'street1', 'John', '30', None, None],
[None, None, 'Peter', '31', '2015', 'red'],
['city2', 'street2', None, None, '2017', 'green']]
请注意,可以将末端附近的部分写成这样,以使其更“受数据驱动”:
items = (('address', 'city'),
('address', 'street'),
('person', 'name'),
('person', 'age'),
('car', 'year'),
('car', 'color'))
for s in source:
data.append([s[k1][k2] for k1, k2 in items])
答案 1 :(得分:1)
分别处理None
情况:
for s in source:
address = s['address']
data.append(
[None, None] if address is None
else [address['city'], address['street']]
)
答案 2 :(得分:1)
您必须先检查地址是否为空,然后再尝试从中访问内容。 例如:
for s in source:
if s['address']:
data.append([s['address']['city]',s['address']['street']])
else:
# whatever behaviour you want for None values
答案 3 :(得分:1)
问题在于,在第二种情况下,s ['address']的计算结果为无,并且无法下标。您应检查该值是否不是None并分别处理这种情况:
import json
x = '''[{"address":{"city": "city1","street": "street1"}},
{"address": null},
{"address":{"city": "city2","street": "street2"}}]'''
source = json.loads(x)
data = []
for s in source:
if s['address'] is not None:
data.append([s['address']['city'],
s['address']['street']])
else:
data.append(None)
print(data)
这将打印:[['city1', 'street1'], None, ['city2', 'street2']]
编辑: 试试这个:
import pandas as pd
df = pd.io.json.json_normalize(source)
df = df.where((pd.notnull(df)), None)
data = df[[column for column in df.columns if '.' in column]]
print(data.values.tolist())
输出: [['city1','street1',无,无,'30','约翰'],[无,无,'红色','2015','31','彼得'],['city2', 'street2','green','2017',无,无]]