Separar parsing de aceitação
Um decoder conhece sintaxe e conversões; não conhece as regras do teu serviço. Um JSON que produz um dicionário pode conter nomes repetidos que já foram reduzidos ao último valor. Se o contrato proíbe repetição, verifica os pares durante o decoding, por exemplo com object_pairs_hook, antes de perder essa informação. Depois valida campos obrigatórios, tipos, limites e relações entre valores. bool é subclasse de int, pelo que isinstance(value, int) aceita True; explicita se isso é permitido. Define também limites de entrada antes da alocação do documento. Rejeitar um milhão de registos depois de os carregar não limita o custo inicial.
Preservar significado numérico
Para um montante decimal, parse_float=Decimal permite construir a partir do token textual sem passar primeiro por float. Isso não define por si só moeda, escala, arredondamento ou limites. Confirma finitude: Decimal também representa NaN e infinidades. O decoder json aceita certas constantes não finitas por defeito; parse_constant pode rejeitá-las. Mas amount="NaN" é uma string e não passa por esse tratamento como constante numérica. Na saída, allow_nan=False trata valores float especiais durante serialização. Não confundas essas opções nem assumas que uma conversão válida torna todos os valores elegíveis para cálculo financeiro.
Acordar a representação completa
Produtor e consumidor precisam do mesmo contrato de formato. ensure_ascii pode representar Évora com um escape sem remover o acento; isso é diferente de converter um Decimal para string com default=str, que altera o tipo JSON entregue. Chaves de objetos JSON são texto: identidades Python 7 e "7" precisam de um modelo sem colisões se representam entidades distintas. Finalmente, dois dump consecutivos não criam automaticamente um array nem um protocolo de múltiplos documentos. Escolhe um documento único ou framing explicitamente suportado por ambos os lados. Testa o round trip e os tipos recebidos, não apenas a aparência do ficheiro.
Consumir sem perder a fronteira de entrega
Um iterador guarda estado de consumo. Contar linhas com sum pode esgotar exatamente o objeto que pretendias percorrer depois. Se precisas de duas passagens, decide entre recriar a fonte, guardar dados limitados ou outra estratégia com custos conhecidos. Para emparelhar IDs e montantes, zip normal termina no mais curto; strict=True deteta comprimentos diferentes quando a iteração chega a essa diferença. Como a avaliação é gradual, operações anteriores do ciclo podem já ter produzido efeitos. Valida integralmente antes da publicação quando o contrato exige um lote completo, usando staging ou um protocolo transacional compatível com o volume e o consumidor.
Gerir retenção e vida dos recursos
A interface lazy não garante memória constante nem recursos abertos. Em tee, um consumidor muito atrasado pode obrigar à retenção de muitos valores; os iteradores resultantes também não são uma solução automática para consumo concorrente entre threads. Uma expressão geradora devolvida dentro de with open pode tentar ler só depois do fecho do ficheiro. Define quem abre, quem consome e quem fecha. A limpeza deve preservar a falha: um return no finally pode mascarar a exceção e transformar leitura falhada em sucesso vazio. Os ensaios precisam de observar valores, exceções e efeitos já produzidos, incluindo fim prematuro e dados parciais.
import json
def unique_names(pairs):
result = {}
for name, value in pairs:
if name in result:
raise ValueError("repeated field: " + name)
result[name] = value
return result
payload = '{"batch":"B-42","limit":12,"limit":24}'
try:
json.loads(payload, object_pairs_hook=unique_names)
except ValueError as exc:
print(str(exc))Exercício original: o objeto de configuração de B-42 apresenta limit duas vezes. O hook rejeita o segundo nome em vez de escolher silenciosamente um valor. Este ensaio não valida um schema completo: acrescenta separadamente campos obrigatórios, tipos, finitude e limites antes de aceitar uma configuração.
Armadilhas comuns
Tratar loads como schema validator; validar duplicados depois de dict; converter precisão em float por conveniência; reutilizar iteradores esgotados; assumir que strict faz rollback; esconder erros no finally.
Tópicos relacionados: Funções pequenas, contratos claros · Erros e ficheiros com contexto · Precisão, dados externos e tempo · Automação observável e repetível
Valida antes de perder informação e antes de publicar efeitos; tipos, limites, identidade e vida dos recursos fazem parte do contrato.
Referência: Python3.14: JSON encoder and decoder · Python 3.14; DR Python 2026.3