JSON.loads () ValueError Datos adicionales en Python

Estoy tratando de leer los valores individuales de un feed JSON. Aquí hay un ejemplo de los datos del feed:

{ "sendtoken": "token1", "bytes_transferred": 0, "num_retries": 0, "timestamp": 1414395374, "queue_time": 975, "message": "internalerror", "id": "mailerX", "m0": { "binding_group": "domain.com", "recipient_domain": "hotmail.com", "recipient_local": "destination", "sender_domain": "domain.com", "binding": "mail.domain.com", "message_id": "C1/34-54876-D36FA645", "api_credential": "creds", "sender_local": "localstring" }, "rejecting_ip": "145.5.5.5", "type": "alpha", "message_stage": 3 } { "sendtoken": "token2", "bytes_transferred": 0, "num_retries": 0, "timestamp": 1414397568, "queue_time": 538, "message": "internal error, "id": "mailerX", "m0": { "binding_group": "domain.com", "recipient_domain": "hotmail.com", "recipient_local": "destination", "sender_domain": "domain.com", "binding": "mail.domain.com", "message_id": "C1/34-54876-D36FA645", "api_credential": "creds", "sender_local": "localstring" }, "rejecting_ip": "145.5.5.5", "type": "alpha", "message_stage": 3 } 

No puedo compartir la URL real, pero los anteriores son los primeros 2 de aproximadamente 150 resultados que se muestran si ejecuto

 print results 

antes de

 json.loads() 

línea.

Mi código:

 import urllib2 import json results = urllib2.urlopen(url).read() jsondata = json.loads(results) for row in jsondata: print row['sendtoken'] print row['recipient_domain'] 

Me gustaría salida como

 token1 hotmail.com 

para cada entrada.

Estoy recibiendo este error:

 ValueError: Extra data: line 2 column 1 - line 133 column 1 (char 583 - 77680) 

Estoy lejos de ser un experto en Python, y esta es la primera vez que trabajo con JSON. He pasado bastante tiempo buscando en Google y Stack Overflow, pero no puedo encontrar una solución que funcione para mi formato de datos específico.

El problema es que sus datos no forman un objeto JSON, por lo que no puede decodificarlos con json.loads .


Primero, esto parece ser una secuencia de objetos JSON separados por espacios. Ya que no nos dirá nada de dónde provienen los datos, esto es realmente una suposición educada; Esperemos que la documentación o el compañero de trabajo o lo que sea que le hayan contado acerca de esta URL le indiquen cuál es el formato real. Pero supongamos que mi suposición educada es correcta.

La forma más fácil de analizar una secuencia de objetos JSON en Python es usar el método raw_decode . Algo como esto:*

 import json def parse_json_stream(stream): decoder = json.JSONDecoder() while stream: obj, idx = decoder.raw_decode(stream) yield obj stream = stream[idx:].lstrip() 

Sin embargo, también hay un error en el segundo objeto JSON en la secuencia. Mira esta parte:

 … "message": "internal error, "id": "mailerX", … 

Falta un "internal error " después "internal error . Si arregla eso, entonces la función anterior iterará dos objetos JSON.

Es de esperar que ese error haya sido causado por el hecho de que usted trató de “copiar y pegar” los datos manualmente al reescribirlos. Si está en su fuente original, tiene un problema mucho mayor; es probable que necesite escribir un analizador “JSON roto” desde cero que pueda adivinar heurísticamente en qué pretenden ser los datos. O, por supuesto, haz que quien esté generando la fuente lo genere adecuadamente.


* En general, es más eficiente usar el segundo argumento de raw_decode para pasar un índice de inicio, en lugar de cortar una copia del rest cada vez. Pero raw_decode no puede manejar los espacios en blanco raw_decode . Es un poco más fácil simplemente cortar y eliminar que escribir código que salta espacios en blanco del índice dado, pero si la memoria y los costos de rendimiento de esas copias son importantes, debe escribir el código más complicado.

Esto se debe a que json.loads (y json.load) no descodifica múltiples objetos json. Por ejemplo, el archivo json que desea puede ser: [“a”: 1, “b”: 2] sin embargo, exactamente el archivo de estructura del código es: [“a”: 1, “b”: 2] [“a “: 1,” b “: 2]