143 votes

Itération dans un objet JSON

J'essaie d'itérer dans un objet JSON pour importer des données, c'est-à-dire le titre et le lien. Je ne parviens pas à atteindre le contenu qui se trouve au-delà de la limite de l'objet JSON. : .

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 n'imprime que l'information avant : . ( ignorez le titre de Justin Bieber :))

134voto

tzot Points 32224

Je pense 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 song.iteritems au lieu de song.items si dans Python 2.

100voto

Thomas Wouters Points 38811

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

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

que vous devriez vraiment faire :

json_object = json.load(raw)

Vous ne devez pas considérer ce que vous obtenez comme un "objet JSON". Ce que vous avez est une liste. La liste contient deux dicts. Les dicts contiennent diverses paires clé/valeur, toutes des chaînes de caractères. Lorsque vous faites json_object[0] vous demandez le premier dict de la liste. Lorsque vous itérez sur cette liste, avec for song in json_object[0]: vous itérez sur les clés du dict. Parce que c'est ce que vous obtenez lorsque vous itérez sur le dict. Si vous voulez accéder à la valeur associée à la clé dans ce dict, vous utiliserez, par exemple, json_object[0][song] .

Rien de tout cela n'est spécifique à JSON. Il s'agit simplement de types Python de base, avec leurs opérations de base, comme cela est abordé dans n'importe quel tutoriel.

54voto

Dale Moore Points 11

Cette question a été posée il y a longtemps, mais je voulais contribuer à la manière dont j'itère habituellement dans un objet JSON. Dans l'exemple ci-dessous, j'ai montré une chaîne codée en dur qui contient 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()

26voto

jcea Points 183

Après avoir désérialisé le JSON, vous avez un objet python. Utilisez les méthodes habituelles des objets.

Dans ce cas, vous avez une liste composée de dictionnaires :

json_object[0].items()

json_object[0]["title"]

etc.

8voto

Mike Graham Points 22480

Je résoudrais ce problème plutôt comme ceci

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X