Iterando a través de un objeto JSON

109

Estoy tratando de iterar a través de un objeto JSON para importar datos, es decir, título y enlace. Parece que no puedo acceder al contenido que está más allá del :.

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

Intenté usar un diccionario:

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

Este código solo imprime la información anterior :. ( ignora la pista de Justin Bieber :))

myusuf3
fuente

Respuestas:

79

Su carga de datos JSON es un poco frágil. En vez de:

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

realmente deberías hacer:

json_object = json.load(raw)

No debería pensar en lo que obtiene como un "objeto JSON". Lo que tienes es una lista. La lista contiene dos dictados. Los dictados contienen varios pares clave / valor, todas cadenas. Cuando lo haga json_object[0], estará pidiendo el primer diccionario de la lista. Cuando iteras sobre eso, con for song in json_object[0]:, iteras sobre las claves del dict. Porque eso es lo que obtienes cuando repites el dictado. Si desea acceder al valor asociado a la clave en que dict, se utilizaría, por ejemplo, json_object[0][song].

Nada de esto es específico de JSON. Son solo tipos básicos de Python, con sus operaciones básicas como se cubre en cualquier tutorial.

Thomas Wouters
fuente
no lo entiendo. Traté de repetir lo que dice tu dicho fuera de los límites. Estoy bastante seguro de que es una pregunta sobre json
myusuf3
7
No. Te digo que repetir el dictado te da las claves. Si desea iterar sobre otra cosa, tendrá que iterar sobre otra cosa. No dijiste lo que querías repetir. Un tutorial de Python sería un buen lugar para averiguar sobre qué puede iterar y qué haría.
Thomas Wouters
5
Desafortunadamente, es un poco difícil explicar todas las formas en que puede extraer datos de listas y diccionarios y cadenas de 600 caracteres que puede incluir en un comentario. Ya dije que debería indexar el dict para obtener el valor asociado con una clave. No estoy seguro de lo que quieres repetir. Aprender sobre los tipos de Python integrados es el siguiente paso.
Thomas Wouters
No hay mucha iteración involucrada cuando desea obtener elementos individuales. Quizás lo que desea iterar es json_object, no json_object[0], y luego obtener elementos individuales de cada dictado.
Thomas Wouters
101

Creo que probablemente quisiste decir:

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: podría usar en song.iteritemslugar de song.itemsif en Python 2.

tzot
fuente
para atributo, valor en song.iteritems (): ¿qué significa la coma en esta línea?
zakdances
Es lo mismo que for (attribute, value) in song.iteritems():, o (var1, var2) = (1, 2)o var1, var2 = 1, 2. dict.iteritems()produce (key, value)pares (tuplas). Busque "desempaquetado de tuplas de Python".
tzot
1
Para python 3, cambie song.iteritemsa song.items.
Big Pumpkin
44

Esta pregunta ha estado aquí durante mucho tiempo, pero quería contribuir a cómo suelo iterar a través de un objeto JSON. En el siguiente ejemplo, he mostrado una cadena codificada que contiene el JSON, pero la cadena JSON podría provenir fácilmente de un servicio web o un archivo.

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
fuente
2
No hay subíndices de cadena en el código anterior; jsonObjectes un dict. En el código anterior, preferiría for key, value in jsonObject.items():.
tzot
22

Después de deserializar el JSON, tiene un objeto Python. Utilice los métodos de objetos habituales.

En este caso, tiene una lista de diccionarios:

json_object[0].items()

json_object[0]["title"]

etc.

jcea
fuente
8

Resolvería este problema más así

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
fuente
3

para iterar a través de JSON puede usar esto:

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
fuente
2

Para Python 3, debe decodificar los datos que obtiene del servidor web. Por ejemplo, decodifico los datos como utf8 y luego lo trato:

 # 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 no decodifica, obtendrá bytes frente a errores de cadena en Python 3.

jamescampbell
fuente