Dados e formatos9 min de leitura

CSV para JSON: por que o arquivo do cliente sempre quebra a importação

Ponto e vírgula como separador, Windows-1252 em vez de UTF-8, vírgula decimal, zero à esquerda que some e BOM invisível. Os cinco problemas que fazem toda importação de CSV falhar no Brasil — e como tratar cada um.

Publicado em

AL

Por André Leitão

Desenvolvedor de software

A importação funciona perfeitamente com o arquivo de exemplo. Vai para produção, o primeiro cliente envia a planilha dele, e tudo cai em uma coluna só — ou os acentos viram símbolos, ou os CPFs perderam o zero da frente. O CSV tem fama de formato simples e é exatamente essa fama que faz a importação ser subestimada no planejamento.

A raiz do problema é que CSV não é um formato: é uma convenção com variações. E o conjunto de variações que aparece em arquivos brasileiros tem particularidades próprias, quase todas herdadas do formato regional do Excel.

Armadilha 1 — o separador é ponto e vírgula

Em português, a vírgula é o separador decimal: escrevemos 1.234,56. Se o Excel usasse vírgula também para separar campos, o valor 1.234,56 viraria dois campos. A solução dele é usar ponto e vírgula, e o resultado é que a maioria dos CSVs gerados por usuários brasileiros não é separada por vírgula, apesar do nome do formato.

O mesmo dado nos dois formatos regionais
# Exportado em inglês
nome,valor,data
Maria Souza,1234.56,2026-03-15

# Exportado em português
nome;valor;data
Maria Souza;1234,56;15/03/2026

Repare que a diferença não para no separador: o decimal e o formato de data também mudam. Um parser que só trata o separador ainda vai converter 1234,56 para o número 1234 ou falhar.

Detecção do separador pela linha de cabeçalho
function detectarSeparador(primeiraLinha) {
  const candidatos = [";", ",", "\t", "|"];

  // O separador correto é o que aparece mais vezes no cabeçalho,
  // já que nomes de coluna raramente contêm delimitadores.
  return candidatos.reduce((melhor, candidato) => {
    const ocorrencias = primeiraLinha.split(candidato).length - 1;
    const melhorOcorrencias = primeiraLinha.split(melhor).length - 1;
    return ocorrencias > melhorOcorrencias ? candidato : melhor;
  }, ",");
}

Armadilha 2 — a codificação não é UTF-8

O Excel em português, ao salvar como CSV, ainda usa Windows-1252 por padrão em muitas versões. Um arquivo assim, lido como UTF-8, transforma cada caractere acentuado em um símbolo estranho: São Paulo vira São Paulo.

O mesmo caractere em duas codificações
CaractereBytes em UTF-8Bytes em Windows-1252Lido como UTF-8
ãC3 A3E3caractere inválido
çC3 A7E7caractere inválido
éC3 A9E9caractere inválido
ã (mojibake)resultado de ler UTF-8 como Latin-1

A correção certa é na origem: pedir ao usuário que salve como CSV UTF-8, opção disponível nas versões recentes do Excel. Quando isso não é viável, dá para detectar a codificação por heurística e reprocessar, mas a detecção nunca é perfeita e falha justamente em arquivos curtos.

Armadilha 3 — o BOM invisível

Alguns programas escrevem três bytes no início do arquivo UTF-8 — EF BB BF, a marca de ordem de bytes. Ela não aparece em nenhum editor, mas o parser a lê como parte do primeiro campo do cabeçalho.

O sintoma é característico e desnorteante: a coluna existe, o dado está lá, mas o acesso pelo nome devolve indefinido. Ao inspecionar o objeto no console, a chave parece exatamente igual à que você digitou.

Remoção do BOM antes de qualquer processamento
function removerBom(texto) {
  // U+FEFF é invisível e gruda no nome da primeira coluna.
  return texto.charCodeAt(0) === 0xfeff ? texto.slice(1) : texto;
}

const conteudo = removerBom(await arquivo.text());

Armadilha 4 — aspas e o separador dentro do campo

Um endereço como Rua das Flores, 120 contém o separador. A convenção é envolver o campo em aspas duplas, e escapar uma aspa interna duplicando-a. Isso significa que um parser correto não pode simplesmente dividir a linha pelo separador — ele precisa percorrer caractere a caractere, controlando se está ou não dentro de aspas.

Uma linha de CSV mais difícil do que parece
nome;endereco;observacao
Maria Souza;"Rua das Flores, 120";"Cliente disse ""urgente"" no pedido"

Um split simples pelo ponto e vírgula produziria quatro campos onde existem três, e ainda deixaria as aspas no valor. É o motivo pelo qual escrever o próprio parser de CSV costuma ser mais caro do que parece — a estrutura de aspas, quebras de linha dentro do campo e escapes cobre mais casos do que a primeira versão prevê.

Armadilha 5 — a conversão automática de tipos

CSV não carrega tipo. Todo valor é texto, e converter é uma decisão do importador — decisão que erra de formas específicas e caras em dados brasileiros.

O que a inferência automática costuma estragar
Valor no CSVInferência ingênuaO que deveria ser
0001234567812345678 (número)texto, é um CPF
01310-100texto ou datatexto, é um CEP
1234,561234 ou NaNnúmero 1234.56
15/03/2026texto ou data erradadata, formato dia/mês/ano
ABC1D23textotexto, é uma placa Mercosul
3E2300 (notação científica)texto, provavelmente um código

A última linha é a mais traiçoeira: um código de produto como 3E2 é interpretado como notação científica por várias linguagens e vira o número 300. O dado é corrompido sem nenhum erro, e a descoberta acontece meses depois.

Uma ordem de processamento que funciona

  1. 1Leia o arquivo como bytes e determine a codificação antes de decodificar para texto.
  2. 2Remova o BOM, se houver, antes de olhar para o cabeçalho.
  3. 3Normalize as quebras de linha, já que arquivos do Windows usam CRLF e os de outros sistemas usam LF.
  4. 4Detecte o separador pela linha de cabeçalho e permita que o usuário corrija.
  5. 5Faça o parse respeitando aspas, aspas escapadas e quebras de linha dentro de campos.
  6. 6Normalize os nomes das colunas — remova espaços nas pontas e padronize a caixa.
  7. 7Converta tipos apenas nas colunas declaradas como numéricas ou de data.
  8. 8Mostre uma prévia das primeiras linhas antes de gravar qualquer coisa.

O passo oito é o que mais reduz suporte. Uma prévia de cinco linhas com as colunas já separadas revela erro de delimitador, de codificação e de mapeamento antes que o usuário importe dez mil registros errados.

Testando a importação

Monte uma pasta de arquivos-problema e rode a importação contra ela na suíte automatizada. O conjunto mínimo tem seis arquivos: separado por vírgula, separado por ponto e vírgula, em Windows-1252, com BOM, com aspas e vírgulas dentro de campos, e com colunas de documento que têm zero à esquerda.

O conversor CSV para JSON do Codigio Labs ajuda na etapa de diagnóstico: colando uma amostra do arquivo do cliente, dá para ver rapidamente como as colunas estão sendo separadas e se os acentos sobreviveram. O processamento acontece no navegador, então planilhas com dados de clientes não precisam ser enviadas a um serviço externo — ainda assim, o ideal é trabalhar com uma amostra anonimizada.

Resumo

  • CSV brasileiro costuma ser separado por ponto e vírgula, porque a vírgula é o separador decimal.
  • Windows-1252 em vez de UTF-8 é a segunda causa mais comum de falha, e corrompe os acentos.
  • O BOM é invisível e gruda no nome da primeira coluna, causando campo indefinido sem erro.
  • Aspas, escapes e separadores dentro de campos exigem parser real, não split.
  • Documentos e códigos são texto: zero à esquerda é informação, e 3E2 não é trezentos.

Perguntas frequentes

Por que o Excel em português salva CSV com ponto e vírgula?
Porque no formato regional brasileiro a vírgula é o separador decimal. Usá-la também como separador de campos tornaria o arquivo ambíguo, então o Excel adota o ponto e vírgula. É o comportamento correto para o formato regional e a causa número um de importação que joga tudo em uma coluna só.
Como descobrir qual separador o arquivo usa?
Conte as ocorrências de vírgula e de ponto e vírgula na linha de cabeçalho: o caractere que aparece um número de vezes igual ao número de colunas menos um é o separador. É a heurística que praticamente todo parser usa, e ela erra justamente quando um cabeçalho contém o outro caractere.
O que é o BOM e por que ele quebra a primeira coluna?
É uma marca de três bytes que alguns programas colocam no início de arquivos UTF-8. Se o parser não a remove, ela gruda no nome da primeira coluna, que passa a ser algo como \ufeffnome em vez de nome — e todo acesso a esse campo devolve indefinido, sem erro visível.
Devo converter os números do CSV automaticamente?
Com cuidado. A inferência automática transforma um CEP como 01310-100 em algo errado e come o zero à esquerda de um CPF. A regra segura é converter apenas as colunas que você sabe serem numéricas e manter documentos, códigos e identificadores como texto.
Existe um padrão oficial de CSV?
Existe a RFC 4180, mas ela é uma descrição de prática comum, não uma norma que os programas sigam. Na prática cada exportador tem suas peculiaridades de separador, aspas, quebra de linha e codificação, e o parser precisa ser tolerante.

Ferramentas relacionadas

AL

Sobre o autor

Desenvolvedor de software no Brasil. Mantém o Codigio Labs desde a primeira ferramenta, escreve os artigos do site e revisa os textos quando a informação técnica muda.

Encontrou um erro ou tem uma correção a sugerir? Fale com o Codigio Labs. Correções relevantes são aplicadas com atualização da data de revisão do texto.

Continue lendo