Carga y análisis de un archivo JSON con varios objetos JSON

101

Estoy tratando de cargar y analizar un archivo JSON en Python . Pero estoy atascado tratando de cargar el archivo:

import json
json_data = open('file')
data = json.load(json_data)

Rendimientos:

ValueError: Extra data: line 2 column 1 - line 225116 column 1 (char 232 - 160128774)

Miré 18.2. json- Codificador y decodificador JSON en la documentación de Python, pero es bastante desalentador leer esta documentación de aspecto horrible.

Primeras líneas (anonimizadas con entradas aleatorias):

{"votes": {"funny": 2, "useful": 5, "cool": 1}, "user_id": "harveydennis", "name": "Jasmine Graham", "url": "http://example.org/user_details?userid=harveydennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 2, "cool": 4}, "user_id": "njohnson", "name": "Zachary Ballard", "url": "https://www.example.com/user_details?userid=njohnson", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 0, "cool": 4}, "user_id": "david06", "name": "Jonathan George", "url": "https://example.com/user_details?userid=david06", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 6, "useful": 5, "cool": 0}, "user_id": "santiagoerika", "name": "Amanda Taylor", "url": "https://www.example.com/user_details?userid=santiagoerika", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 8, "cool": 2}, "user_id": "rodriguezdennis", "name": "Jennifer Roach", "url": "http://www.example.com/user_details?userid=rodriguezdennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
Pi_
fuente

Respuestas:

222

Tiene un archivo de texto con formato JSON Lines . Necesita analizar su archivo línea por línea:

import json

data = []
with open('file') as f:
    for line in f:
        data.append(json.loads(line))

Cada línea contiene JSON válido, pero como un todo, no es un valor JSON válido ya que no hay una lista de nivel superior o una definición de objeto.

Tenga en cuenta que debido a que el archivo contiene JSON por línea, se ahorra los dolores de cabeza de tratar de analizarlo todo de una vez o de encontrar un analizador JSON de transmisión. Ahora puede optar por procesar cada línea por separado antes de pasar a la siguiente, ahorrando memoria en el proceso. Probablemente no desee agregar cada resultado a una lista y luego procesar todo si su archivo es realmente grande.

Si tiene un archivo que contiene objetos JSON individuales con delimitadores en el medio, use ¿Cómo uso el módulo 'json' para leer un objeto JSON a la vez? para analizar objetos individuales utilizando un método almacenado en búfer.

Martijn Pieters
fuente
2
+1 Quizás valga la pena señalar que si no necesita todos los objetos a la vez, procesarlos uno por uno puede ser un enfoque más eficiente. De esta manera, no necesitará almacenar datos completos en la memoria, sino una sola pieza.
Tadeck
1
@Pi_: tendrás un diccionario, así que accede a los campos como claves:data = json.loads(line); print data[u'votes']
Martijn Pieters
1
@Pi_: imprime el resultado de json.loads () luego o usa el depurador para inspeccionar.
Martijn Pieters
1
@Pi_: no; no confunda el formato JSON con la representación de dict de Python. Ahora está viendo diccionarios de Python con cadenas.
Martijn Pieters
1
@ user2441441: vea la respuesta vinculada de la publicación aquí.
Martijn Pieters
11

para aquellos que se topan con esta pregunta: la jsonlinesbiblioteca de Python (mucho más joven que esta pregunta) maneja elegantemente archivos con un documento json por línea. ver https://jsonlines.readthedocs.io/

wouter bolsterlee
fuente
4

Eso está mal formateado. Tiene un objeto JSON por línea, pero no están contenidos en una estructura de datos más grande (es decir, una matriz). Deberá reformatearlo para que comience [y termine con ]una coma al final de cada línea, o analizarlo línea por línea como diccionarios separados.

Daniel Roseman
fuente
20
Con un archivo de 50 MB, el OP probablemente esté mejor tratando con los datos línea por línea de todos modos. :-)
Martijn Pieters
11
El formato incorrecto del archivo depende del punto de vista de cada uno. Si estaba destinado a tener el formato "líneas JSON", es válido. Ver: jsonlines.org
LS