Iterowanie po obiekcie JSON

111

Próbuję iterować przez obiekt JSON, aby zaimportować dane, tj. Tytuł i łącze. Wydaje się, że nie mogę dotrzeć do treści, które są starsze niż :.

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
    }
]

Próbowałem użyć słownika:

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

Ten kod wyświetla tylko informacje wcześniej :. ( zignoruj ​​utwór Justina Biebera :))

myusuf3
źródło

Odpowiedzi:

80

Ładowanie danych JSON jest trochę kruche. Zamiast:

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

powinieneś po prostu zrobić:

json_object = json.load(raw)

Nie powinieneś myśleć o tym, co otrzymujesz jako o „obiekcie JSON”. Masz listę. Lista zawiera dwie dykty. Dykty zawierają różne pary klucz / wartość, wszystkie ciągi. Kiedy to robisz json_object[0], pytasz o pierwszy dykt na liście. Kiedy to for song in json_object[0]:robisz, iterujesz po klawiszach dyktatu. Ponieważ to właśnie otrzymujesz, powtarzając dyktando. Jeśli chcesz uzyskać dostęp do wartości skojarzonej z kluczem w tym dyktacie, możesz użyć na przykład json_object[0][song].

Nic z tego nie jest specyficzne dla formatu JSON. To tylko podstawowe typy Pythona, których podstawowe operacje są opisane w dowolnym samouczku.

Thomas Wouters
źródło
nie rozumiem. Próbowałem powtórzyć to, co mówi twoje powiedzenie poza granicami. jestem prawie pewien, że to pytanie o json
myusuf3
7
Nie. Mówię ci, że iteracja dyktowania daje ci klucze. Jeśli chcesz powtórzyć coś innego, będziesz musiał powtórzyć coś innego. Nie powiedziałeś, co chciałeś powtórzyć. Samouczek Pythona byłby dobrym miejscem, aby dowiedzieć się, co możesz powtórzyć i co by to zrobiło.
Thomas Wouters
5
Niestety trochę trudno jest wyjaśnić wszystkie sposoby wyodrębniania danych z list, słowników i łańcuchów zawierających 600 znaków, które można umieścić w komentarzu. Powiedziałem już, że należy zindeksować dyktę, aby uzyskać wartość związaną z kluczem. Nie jestem pewien, co chcesz powtórzyć. Następnym krokiem jest poznanie wbudowanych typów Pythona.
Thomas Wouters
Nie ma zbyt wielu iteracji, gdy chcesz uzyskać pojedyncze elementy. Być może to, co chcesz iterować, to json_objectnie json_object[0], a następnie uzyskać poszczególne elementy z każdego dyktu.
Thomas Wouters
102

Myślę, że prawdopodobnie miałeś na myśli:

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

Uwaga: w Pythonie 2 można użyć song.iteritemszamiast song.itemsif.

tzot
źródło
dla atrybutu wartość w song.iteritems (): co oznacza przecinek w tym wierszu?
zakdances
To jest to samo co for (attribute, value) in song.iteritems():, lub (var1, var2) = (1, 2)lub var1, var2 = 1, 2. dict.iteritems()tworzy (key, value)pary (krotki). Wyszukaj „python tuple unpacking”.
tzot
1
W przypadku Pythona 3 zmień song.iteritemsna song.items.
Big Pumpkin
44

To pytanie było tu od dawna, ale chciałem wspomnieć, jak zwykle iteruję przez obiekt JSON. W poniższym przykładzie pokazałem zakodowany na stałe ciąg zawierający JSON, ale ciąg JSON mógłby równie łatwo pochodzić z usługi internetowej lub pliku.

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
źródło
3
W powyższym kodzie nie ma indeksów łańcuchowych; jsonObjectjest dict. W powyższym kodzie wolałbym for key, value in jsonObject.items():.
tzot
22

Po deserializacji JSON masz obiekt Pythona. Użyj zwykłych metod obiektowych.

W tym przypadku masz listę utworzoną ze słowników:

json_object[0].items()

json_object[0]["title"]

itp.

jcea
źródło
8

Rozwiązałbym ten problem bardziej w ten sposób

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
źródło
3

do iteracji po JSON możesz użyć tego:

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
źródło
2

W przypadku Pythona 3 musisz zdekodować dane otrzymane z serwera internetowego. Na przykład dekoduję dane jako utf8, a następnie radzę sobie z tym:

 # 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

Jeśli nie dekodujesz, otrzymasz błędy bajtów w porównaniu z ciągami znaków w Pythonie 3.

jamescampbell
źródło