首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中导航多维JSON数组

在Python中导航多维JSON数组
EN

Stack Overflow用户
提问于 2013-10-21 17:34:49
回答 3查看 18.7K关注 0票数 8

我正在尝试弄清楚如何在Python中查询JSON数组。有人能告诉我如何在一个相当复杂的数组中进行简单的搜索和打印吗?

我使用的示例如下:http://eu.battle.net/api/wow/realm/status

例如,我想看看如何找到'Silvermoon‘服务器,并打印出它的'population',然后是'Wintergrasp’数组中的‘controlling print’。

数组片段目前看起来如下所示:

代码语言:javascript
复制
{"type":"pve","population":"high","queue":false,"wintergrasp":{"area":1,"controlling-faction":0,"status":0,"next":1382350068792},"tol-barad":{"area":21,"controlling-faction":0,"status":0,"next":1382349141932},"status":true,"name":"Silvermoon","slug":"silvermoon","battlegroup":"Cyclone / Wirbelsturm","locale":"en_GB","timezone":"Europe/Paris"}

目前,我可以访问主数组,但似乎无法访问子数组,除非将整个操作复制到另一个新变量中,这似乎很浪费。我希望能够做一些像这样的事情

代码语言:javascript
复制
import urllib2
import json

req = urllib2.Request("http://eu.battle.net/api/wow/realm/status", None, {})
opener = urllib2.build_opener()
f = opener.open(req)

x = json.load(f)  # open the file and read into a variable

# search and find the Silvermoon server
silvermoon_array = ????

# print the population
print silvermoon_array.????

# access the Wintergrasp sub-array
wintergrasp_sub = ????
print wintergrasp_sub.????  # print the controlling-faction variable

这将真正帮助我掌握如何访问其他东西。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-21 18:14:38

Python的interactive mode是逐步探索结构化数据的好方法。很容易找到如何访问,比方说,silvermoon服务器数据:

代码语言:javascript
复制
>>> data=json.load(urllib2.urlopen("http://eu.battle.net/api/wow/realm/status"))
>>> type(data)
<type 'dict'>
>>> data.keys()
[u'realms']
>>> type(data['realms'])
<type 'list'>
>>> type(data['realms'][0])
<type 'dict'>
>>> data['realms'][0].keys()
[u'status', u'wintergrasp', u'battlegroup', u'name', u'tol-barad', u'locale', u'queue', u'timezone', u'type', u'slug', u'population']
>>> data['realms'][0]['name']
u'Aegwynn'
>>> [realm['name'] for realm in data['realms']].index('Silvermoon')
212
>>> silvermoon= data['realms'][212]
>>> silvermoon['population']
u'high'
>>> type(silvermoon['wintergrasp'])
<type 'dict'>
>>> silvermoon['wintergrasp'].keys()
[u'status', u'next', u'controlling-faction', u'area']
>>> silvermoon['wintergrasp']['controlling-faction']
>>> silvermoon['population']
u'high'

如果你还不知道它们,你应该在dictionary.keyslist.indexlist comprehensions上阅读,以了解正在发生的事情。

在弄清楚数据的结构之后,您最终可以重写数据访问,使其更具可读性和效率:

代码语言:javascript
复制
realms= data['realms']
realm_from_name= dict( [(realm['name'], realm) for realm in realms])
print realm_from_name['Silvermoon']['population']
print realm_from_name['Silvermoon']['wintergrasp']['controlling-faction']

至于将数组复制到另一个变量是很浪费的,您应该知道python传递的值是by reference。这意味着当你给一个新的变量赋值时,不会涉及复制。Here's a simple explanation of passing by value vs passing by reference

最后,您似乎过于担心性能。Python的哲学是get it right first, optimize later。当你让它正常工作,如果你需要更好的性能,优化它,如果这是值得的话。

票数 12
EN

Stack Overflow用户

发布于 2013-10-21 18:05:50

这就是你想要的:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
import json
import urllib2

def searchListOfDicts(listOfDicts, attr, value):
    """
    Loops through a list of dictionaries and returns matching attribute value pair
    You can also pass it slug, silvermoon or type, pve
    returns a list containing all matching dictionaries 
    """
    matches = [record for record in listOfDicts if attr in record and record[attr] == value]
    return matches

def myjsonDict():
    """
    Opens url, grabs json and puts it inside a dictionary
    """
    req = urllib2.Request("http://eu.battle.net/api/wow/realm/status", None, {})
    opener = urllib2.build_opener()
    f = opener.open(req)
    json_dict = json.load(f)
    return json_dict

jsonDict = myjsonDict()
#we want to search inside realms list
silverMoonServers = searchListOfDicts(jsonDict["realms"], "name", "Silvermoon")
#access first dictionary that matched "name, Silvermoon" query
print silverMoonServers[0]
print silverMoonServers[0]["wintergrasp"]
print silverMoonServers[0]["wintergrasp"]["controlling-faction"]
票数 1
EN

Stack Overflow用户

发布于 2013-10-21 17:48:52

在Python语言中,json.loads将json对象映射到Python字典,并将Arrays映射到list,因此进一步的操作就像常规的python dictlist结构一样。

下面是如何使用requestslamdbas实现这一点

代码语言:javascript
复制
    import json
    import requests

    response = requests.get("http://eu.battle.net/api/wow/realm/status")
    json_data = json.loads(response.text)

    # loop through the list of realms to find the one you need (realm_name)
    get_realm = lambda realm_name, jd: [r for r in jd['realms'] 
                                        if r['name'] == realm_name]

    # extract data you need, if there is a match in the list of realms,
    # return None otherwise
    get_your_data = lambda realm: (
        realm[0]['name'],
        realm[0]['wintergrasp']['controlling-faction']
    ) if realm else None

    print get_your_data(get_realm('Silvermoon', json_data))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19490856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档