Python 将 JSON 数组解析为对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15010418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parsing JSON array into objects?
提问by thebiglebowski11
I'm trying to parse some data in Python I have some JSON:
我正在尝试用 Python 解析一些数据我有一些 JSON:
{
"data sources": [
"http://www.gcmap.com/"
],
"metros": [
{
"code": "SCL",
"continent": "South America",
"coordinates": {
"S": 33,
"W": 71
},
"country": "CL",
"name": "Santiago",
"population": 6000000,
"region": 1,
"timezone": -4
},
{
"code": "LIM",
"continent": "South America",
"coordinates": {
"S": 12,
"W": 77
},
"country": "PE",
"name": "Lima",
"population": 9050000,
"region": 1,
"timezone": -5
}
]
}
If I wanted to parse the "metros" array into and array of Python class Metroobjects, how would I setup the class?
如果我想将“metros”数组解析为 Python 类Metro对象数组,我将如何设置该类?
I was thinking:
我刚在想:
class Metro(object):
def __init__(self):
self.code = 0
self.name = ""
self.country = ""
self.continent = ""
self.timezone = ""
self.coordinates = []
self.population = 0
self.region = ""
So I want to go through each metro and put the data into a corresponding Metroobject and place that object into a Python array of objects...How can I loop through the JSON metros?
所以我想遍历每个地铁并将数据放入相应的Metro对象中,然后将该对象放入对象的 Python 数组中……我如何遍历 JSON 地铁?
采纳答案by nneonneo
If you always get the same keys, you can use **to easily construct your instances. Making the Metroa namedtuplewill simplify your life if you are using it simply to hold values:
如果您始终获得相同的密钥,则可以使用**它轻松构建您的实例。如果您只是使用 a 来保存价值,那么制作Metroanamedtuple将简化您的生活:
from collections import namedtuple
Metro = namedtuple('Metro', 'code, name, country, continent, timezone, coordinates, population, region')
then simply
然后简单地
import json
data = json.loads('''...''')
metros = [Metro(**k) for k in data["metros"]]
回答by James Thiele
Use the json module from the library http://docs.python.org/2/library/json.htmlto convert the json to a Python dictionary
使用库http://docs.python.org/2/library/json.html 中的 json 模块将 json 转换为 Python 字典
回答by Abhijit
Assuming, you are using json to load the data, I would use a list of namedtuple here to store the data under the key 'metro'
假设您正在使用 json 加载数据,我将在此处使用 namedtuple 列表将数据存储在键 'metro' 下
>>> from collections import namedtuple
>>> metros = []
>>> for e in data[u'metros']:
metros.append(namedtuple('metro', e.keys())(*e.values()))
>>> metros
[metro(code=u'SCL', name=u'Santiago', country=u'CL', region=1, coordinates={u'S': 33, u'W': 71}, timezone=-4, continent=u'South America', population=6000000), metro(code=u'LIM', name=u'Lima', country=u'PE', region=1, coordinates={u'S': 12, u'W': 77}, timezone=-5, continent=u'South America', population=9050000)]
>>>
回答by dmg
回答by cmd
Maybe something like
也许像
import json
data = json.loads(<json string>)
data.metros = [Metro(**m) for m in data.metros]
class Metro(object):
def __init__(self, **kwargs):
self.code = kwargs.get('code', 0)
self.name = kwargs.get('name', "")
self.county = kwargs.get('county', "")
self.continent = kwargs.get('continent', "")
self.timezone = kwargs.get('timezone', "")
self.coordinates = kwargs.get('coordinates', [])
self.population = kwargs.get('population', 0)
self.region = kwargs.get('region', 0)
回答by Demian Brecht
In [17]: def load_flat(data, inst):
....: for key, value in data.items():
....: if not hasattr(inst, key):
....: raise AttributeError(key)
....: else:
....: setattr(inst, key, value)
....:
In [18]: m = Metro()
In [19]: load_float(data['metros'][0], m)
In [20]: m.__dict__
Out[20]:
{'code': 'SCL',
'continent': 'South America',
'coordinates': {'S': 33, 'W': 71},
'country': 'CL',
'name': 'Santiago',
'population': 6000000,
'region': 1,
'timezone': -4}
Not only is it very much readable and very explicit about what it does, but it also provides some basic field validation as well (raising exceptions on mismatched fields, etc)
它不仅具有很高的可读性,而且非常明确地说明了它的作用,而且还提供了一些基本的字段验证(在不匹配的字段上引发异常等)
回答by martineau
It's relatively easy to do since you've read the data with json.load()which will return a Python dictionary for each element in "metros" in this case — just walk though it and create the list ofMetroclass instances. I modified the calling sequence of the Metro.__init__()method you had to make it easier to pass data to it from the dictionary returned from json.load().
这样做相对容易,因为您已经阅读了数据,json.load()在这种情况下,这些数据将为“metros”中的每个元素返回一个 Python 字典——只需遍历它并创建Metro类实例列表。我修改了Metro.__init__()方法的调用顺序,您必须使从json.load().
Since each element of the "metros" list in the result is a dictionary, you can just pass that to class Metro's constructor using **notation to turn it into keyword arguments. The constructor can then just update()it's own __dict__to transfer those values to itself.
由于结果中“metros”列表的每个元素都是一个字典,您可以Metro使用**符号将其传递给 class的构造函数以将其转换为关键字参数。构造函数就可以只是update()它自己的__dict__这些值转让给自己。
By doing things this way, instead of using something like a collections.namedtupleas just a data container, is that Metrois a custom class which makes adding other methods and/or attributes you wish to it trivial.
通过以这种方式做事,而不是将 a 之类的东西collections.namedtuple仅用作数据容器,它Metro是一个自定义类,它使添加您希望添加的其他方法和/或属性变得微不足道。
import json
class Metro(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
fields = [' {}={!r}'.format(k,v)
for k, v in self.__dict__.items() if not k.startswith('_')]
return '{}(\n{})'.format(self.__class__.__name__, ',\n'.join(fields))
with open('metros.json') as file:
json_obj = json.load(file)
metros = [Metro(**metro_dict) for metro_dict in json_obj['metros']]
for metro in metros:
print('{}\n'.format(metro))
Output:
输出:
Metro(
code='SCL',
continent='South America',
coordinates={'S': 33, 'W': 71},
country='CL',
name='Santiago',
population=6000000,
region=1,
timezone=-4)
Metro(
code='LIM',
continent='South America',
coordinates={'S': 12, 'W': 77},
country='PE',
name='Lima',
population=9050000,
region=1,
timezone=-5)

