Itérer à travers un objet JSON

110

J'essaye de parcourir un objet JSON pour importer des données, c'est-à-dire le titre et le lien. Je n'arrive pas à accéder au contenu qui dépasse le :.

JSON:

[
    {
        "title": "Baby (Feat. Ludacris) - Justin Bieber",
        "description": "Baby (Feat. Ludacris) by Justin Bieber on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Baby+Feat+Ludacris+/2Bqvdq",
        "pubDate": "Wed, 28 Apr 2010 02:37:53 -0400",
        "pubTime": 1272436673,
        "TinyLink": "http://tinysong.com/d3wI",
        "SongID": "24447862",
        "SongName": "Baby (Feat. Ludacris)",
        "ArtistID": "1118876",
        "ArtistName": "Justin Bieber",
        "AlbumID": "4104002",
        "AlbumName": "My World (Part II);\nhttp://tinysong.com/gQsw",
        "LongLink": "11578982",
        "GroovesharkLink": "11578982",
        "Link": "http://tinysong.com/d3wI"
    },
    {
        "title": "Feel Good Inc - Gorillaz",
        "description": "Feel Good Inc by Gorillaz on Grooveshark",
        "link": "http://listen.grooveshark.com/s/Feel+Good+Inc/1UksmI",
        "pubDate": "Wed, 28 Apr 2010 02:25:30 -0400",
        "pubTime": 1272435930
    }
]

J'ai essayé d'utiliser un dictionnaire:

def getLastSong(user,limit):
    base_url = 'http://gsuser.com/lastSong/'
    user_url = base_url + str(user) + '/' + str(limit) + "/"
    raw = urllib.urlopen(user_url)
    json_raw= raw.readlines()
    json_object = json.loads(json_raw[0])

    #filtering and making it look good.
    gsongs = []
    print json_object
    for song in json_object[0]:   
        print song

Ce code imprime uniquement les informations avant :. ( ignorez la piste de Justin Bieber :))

myusuf3
la source

Réponses:

79

Votre chargement des données JSON est un peu fragile. Au lieu de:

json_raw= raw.readlines()
json_object = json.loads(json_raw[0])

vous devriez vraiment juste faire:

json_object = json.load(raw)

Vous ne devriez pas penser à ce que vous obtenez comme un "objet JSON". Ce que vous avez est une liste. La liste contient deux dictionnaires. Les dictionnaires contiennent diverses paires clé / valeur, toutes des chaînes. Lorsque vous le faites json_object[0], vous demandez le premier dict de la liste. Lorsque vous parcourez cela, avec for song in json_object[0]:, vous parcourez les clés du dict. Parce que c'est ce que vous obtenez lorsque vous parcourez le dict. Si vous souhaitez accéder à la valeur associée à la clé dans cette dict, vous pouvez utiliser, par exemple, json_object[0][song].

Rien de tout cela n'est spécifique à JSON. Ce ne sont que des types Python de base, avec leurs opérations de base décrites dans n'importe quel tutoriel.

Thomas Wouters
la source
je ne comprends pas. J'ai essayé de répéter ce que vous dites hors des limites. Je suis presque sûr que c'est une question sur json
myusuf3
7
Non. Je vous dis qu'itérer le dict vous donne les clés. Si vous voulez itérer sur autre chose, vous devrez itérer sur autre chose. Vous n'avez pas dit ce que vous vouliez répéter. Un didacticiel Python serait un bon endroit pour découvrir ce que vous pouvez parcourir et ce qu'il ferait.
Thomas Wouters
5
Malheureusement, il est un peu difficile d'expliquer toutes les façons dont vous pouvez extraire des données à partir de listes et de dictionnaires et de chaînes dans les 600 caractères que vous pouvez mettre dans un commentaire. J'ai déjà dit que vous devriez indexer le dict pour obtenir la valeur associée à une clé. Je ne sais pas sur quoi vous voulez répéter. La prochaine étape consiste à apprendre les types Python intégrés.
Thomas Wouters
Il n'y a pas beaucoup d'itérations impliquées lorsque vous souhaitez obtenir des éléments individuels. Peut-être que ce que vous voulez parcourir est json_object, non json_object[0], puis obtenir des éléments individuels de chaque dict.
Thomas Wouters
101

Je crois que vous vouliez probablement dire:

from __future__ import print_function

for song in json_object:
    # now song is a dictionary
    for attribute, value in song.items():
        print(attribute, value) # example usage

NB: Vous pouvez utiliser à la song.iteritemsplace de song.itemsif dans Python 2.

tzot
la source
pour attribut, valeur dans song.iteritems (): que signifie la virgule dans cette ligne?
zakdances
C'est la même chose que for (attribute, value) in song.iteritems():, ou (var1, var2) = (1, 2)ou var1, var2 = 1, 2. dict.iteritems()produit des (key, value)paires (tuples). Recherchez «python tuple unpacking».
tzot
1
Pour python 3, passez song.iteritemsà song.items.
Big Pumpkin
44

Cette question est ici depuis longtemps, mais je voulais contribuer à la façon dont j'itère habituellement à travers un objet JSON. Dans l'exemple ci-dessous, j'ai montré une chaîne codée en dur contenant le JSON, mais la chaîne JSON pourrait tout aussi bien provenir d'un service Web ou d'un fichier.

import json

def main():

    # create a simple JSON array
    jsonString = '{"key1":"value1","key2":"value2","key3":"value3"}'

    # change the JSON string into a JSON object
    jsonObject = json.loads(jsonString)

    # print the keys and values
    for key in jsonObject:
        value = jsonObject[key]
        print("The key and value are ({}) = ({})".format(key, value))

    pass

if __name__ == '__main__':
    main()
Dale Moore
la source
2
Il n'y a pas d'indice de chaîne dans le code ci-dessus; jsonObjectest un dict. Dans le code ci-dessus, je préférerais for key, value in jsonObject.items():.
tzot le
22

Après avoir désérialisé le JSON, vous avez un objet python. Utilisez les méthodes d'objet régulières.

Dans ce cas, vous avez une liste de dictionnaires:

json_object[0].items()

json_object[0]["title"]

etc.

jcea
la source
8

Je résoudrais ce problème plus comme ça

import json
import urllib2

def last_song(user, limit):
    # Assembling strings with "foo" + str(bar) + "baz" + ... generally isn't 
    # as nice as using real string formatting. It can seem simpler at first, 
    # but leaves you less happy in the long run.
    url = 'http://gsuser.com/lastSong/%s/%d/' % (user, limit)

    # urllib.urlopen is deprecated in favour of urllib2.urlopen
    site = urllib2.urlopen(url)

    # The json module has a function load for loading from file-like objects, 
    # like the one you get from `urllib2.urlopen`. You don't need to turn 
    # your data into a string and use loads and you definitely don't need to 
    # use readlines or readline (there is seldom if ever reason to use a 
    # file-like object's readline(s) methods.)
    songs = json.load(site)

    # I don't know why "lastSong" stuff returns something like this, but 
    # your json thing was a JSON array of two JSON objects. This will 
    # deserialise as a list of two dicts, with each item representing 
    # each of those two songs.
    #
    # Since each of the songs is represented by a dict, it will iterate 
    # over its keys (like any other Python dict). 
    baby, feel_good = songs

    # Rather than printing in a function, it's usually better to 
    # return the string then let the caller do whatever with it. 
    # You said you wanted to make the output pretty but you didn't 
    # mention *how*, so here's an example of a prettyish representation
    # from the song information given.
    return "%(SongName)s by %(ArtistName)s - listen at %(link)s" % baby
Mike Graham
la source
3

pour itérer via JSON, vous pouvez utiliser ceci:

json_object = json.loads(json_file)
for element in json_object: 
    for value in json_object['Name_OF_YOUR_KEY/ELEMENT']:
        print(json_object['Name_OF_YOUR_KEY/ELEMENT']['INDEX_OF_VALUE']['VALUE'])
Keivan
la source
2

Pour Python 3, vous devez décoder les données que vous récupérez du serveur Web. Par exemple, je décode les données en utf8 puis je les gère:

 # example of json data object group with two values of key id
jsonstufftest = '{'group':{'id':'2','id':'3'}}
 # always set your headers
headers = {'User-Agent': 'Moz & Woz'}
 # the url you are trying to load and get json from
url = 'http://www.cooljson.com/cooljson.json'
 # in python 3 you can build the request using request.Request
req = urllib.request.Request(url,None,headers)
 # try to connect or fail gracefully
try:
    response = urllib.request.urlopen(req) # new python 3 code -jc
except:
    exit('could not load page, check connection')
 # read the response and DECODE
html=response.read().decode('utf8') # new python3 code
 # now convert the decoded string into real JSON
loadedjson = json.loads(html)
 # print to make sure it worked
print (loadedjson) # works like a charm
 # iterate through each key value
for testdata in loadedjson['group']:
    print (accesscount['id']) # should print 2 then 3 if using test json

Si vous ne décodez pas, vous obtiendrez des erreurs d'octets contre des erreurs de chaîne dans Python 3.

jamescampbell
la source