Carregar e analisar um arquivo JSON com vários objetos JSON


101

Estou tentando carregar e analisar um arquivo JSON em Python . Mas estou preso tentando carregar o arquivo:

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

Rendimentos:

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

Eu olhei para 18,2. json- Codificador e decodificador JSON na documentação do Python, mas é muito desanimador ler esta documentação de aparência horrível.

Primeiras linhas (anonimizadas com entradas aleatórias):

{"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"}

Respostas:


222

Você tem um arquivo de texto no formato JSON Lines . Você precisa analisar seu arquivo linha por linha:

import json

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

Cada linha contém JSON válido, mas como um todo, não é um valor JSON válido, pois não há lista de nível superior ou definição de objeto.

Observe que, como o arquivo contém JSON por linha, você evita o trabalho de tentar analisar tudo de uma vez ou descobrir um analisador JSON de streaming. Agora você pode optar por processar cada linha separadamente antes de passar para a próxima, economizando memória no processo. Provavelmente, você não deseja acrescentar cada resultado a uma lista e depois processar tudo se o seu arquivo for muito grande.

Se você tiver um arquivo contendo objetos JSON individuais com delimitadores entre eles, use Como faço para usar o módulo 'json' para ler um objeto JSON por vez? para analisar objetos individuais usando um método de buffer.


2
+1 Talvez seja importante notar que, se você não precisa de todos os objetos de uma vez, processá-los um por um pode ser uma abordagem mais eficiente. Dessa forma, você não precisará armazenar dados inteiros na memória, mas uma única parte deles.
Tadeck

1
@Pi_: você terá um dicionário, então acesse os campos como chaves:data = json.loads(line); print data[u'votes']
Martijn Pieters

1
@Pi_: imprime o resultado de json.loads () e então ou usa o depurador para inspecionar.
Martijn Pieters

1
@Pi_: não; não confunda o formato JSON com a representação python dict. Você está vendo dicionários python com strings agora.
Martijn Pieters

1
@ user2441441: veja a resposta com link da postagem aqui.
Martijn Pieters


4

Isso está mal formatado. Você tem um objeto JSON por linha, mas eles não estão contidos em uma estrutura de dados maior (ou seja, uma matriz). Você precisará reformatá-lo para que comece [e termine com ]uma vírgula no final de cada linha ou analisá-lo linha por linha como dicionários separados.


20
Com um arquivo de 50 MB, é provavelmente melhor para o OP lidar com os dados linha por linha. :-)
Martijn Pieters

11
Se o arquivo está mal formatado depende do ponto de vista de cada um. Se pretendia estar no formato "linhas JSON", é válido. Veja: jsonlines.org
LS
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.