Ir para o conteúdo
jsonbeautifiers
Português

NDJSON para JSON

Transforma registros separados por quebras de linha em um array, e aponta a linha que falha.

NDJSON
Array JSON

Nada do que você cola sai do seu navegador. A lista de permissões connect-src transforma isso em uma garantia do navegador, e não em uma promessa. Confira você mesmo

Transforme JSON delimitado por quebras de linha em um único array. Cada linha é parseada de forma independente, e qualquer linha que falhe é reportada com o número dela em vez de derrubar o arquivo inteiro.

NDJSON é o que sai de pipelines de log, de exportações do BigQuery, de arquivos bulk do Elasticsearch e de APIs em streaming, e é o que causa os erros "Extra data" e "unexpected non-whitespace character" quando alguém tenta parsear como um documento só.

O que é NDJSON

Um valor JSON completo por linha, separados por quebra de linha. Sem vírgulas entre registros, sem array envolvendo. Linhas em branco são ignoradas. As extensões convencionais são .ndjson e .jsonl.

JSON Lines e NDJSON são na prática o mesmo formato descrito por duas especificações pequenas que concordam em tudo que importa. Algumas ferramentas citam uma, outras citam a outra; um arquivo escrito para qualquer uma é lido corretamente pelas duas.

Por que ele existe

Três vantagens reais, todas vindas do fato de os registros serem independentes.

Ele faz streaming
Quem consome processa um registro por vez e nunca segura o arquivo inteiro. Uma exportação de 50 GB tudo bem; um array JSON de 50 GB não.
Ele aceita append
Acrescentar um registro é uma única escrita no fim do arquivo. Acrescentar a um array JSON significa reescrever o colchete de fechamento, o que não é append nenhum.
Ele sobrevive a corrupção
Uma linha malformada custa um registro. Um byte malformado em um array JSON custa o arquivo.

Para que lado converter

Para array quando os dados vão para algum lugar que espera um documento único: um navegador, um corpo de requisição, um arquivo de configuração. Para NDJSON quando vão para um pipeline, um log, um arquivo append-only ou qualquer coisa que faça streaming. As duas direções estão disponíveis acima.

How to do this in code

Lendo e escrevendo NDJSON em código.

py Python

A list comprehension segura tudo em memória. Itere o arquivo direto para processar em fluxo.

import json

# Read
with open('events.ndjson') as f:
    records = [json.loads(line) for line in f if line.strip()]

# Write
with open('events.ndjson', 'w') as f:
    for r in records:
        f.write(json.dumps(r) + '\n')

# pandas knows the format
import pandas as pd
df = pd.read_json('events.ndjson', lines=True)
sh jq

-s recolhe todas as entradas em um array; -c escreve um valor compacto por linha. Essas duas flags são a conversão inteira.

# NDJSON to an array
jq -s . events.ndjson > events.json

# An array to NDJSON
jq -c '.[]' events.json > events.ndjson

# Filter a huge NDJSON file without loading it all
jq -c 'select(.level == "error")' events.ndjson
js Node

crlfDelay: Infinity faz o readline tratar CRLF como uma única quebra, o que importa em arquivos escritos no Windows.

import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';

const rl = createInterface({
  input: createReadStream('events.ndjson'),
  crlfDelay: Infinity,
});

for await (const line of rl) {
  if (!line.trim()) continue;
  const record = JSON.parse(line);
  // one record at a time, constant memory
}

Perguntas frequentes

NDJSON é a mesma coisa que JSON Lines?
Para todo efeito prático, sim. São duas especificações pequenas que concordam no essencial: um valor JSON por linha, UTF-8, separados por quebra de linha. As extensões .jsonl e .ndjson são usadas de forma intercambiável.
Um registro pode ocupar várias linhas?
Não. Esse é justamente o ponto do formato: a quebra de linha é o separador de registros, então cada registro precisa caber em exatamente uma linha. Minifique cada registro antes de escrever.
Por que o meu arquivo NDJSON não faz parsing como JSON?
Porque ele não é um documento JSON, são muitos. O JavaScript reporta "Unexpected non-whitespace character after JSON" e o Python reporta "Extra data". Os dois querem dizer que o parser terminou um valor e encontrou outro.