CS Coder
APIs

JSON no Delphi: leia campos com segurança usando CSCoder.JSON

Três funções para ler strings, inteiros e booleanos com tipos explícitos, sem conversões silenciosas. Unit MIT, exemplo e testes para download.

· 5 min de leitura
Objetivo e formato

Compreender json no delphi e reconhecer os limites do exemplo.

Tutorial · prática orientada · Intermediário
Antes de experimentar

Noções de Object Pascal. Para executar os exemplos, use um ambiente Delphi compatível.

Referência editorial não equivale a compatibilidade verificada. Confira o escopo no texto e no projeto.

Documentação, instalação e limites de CSCoder.JSON

Experimentar o contrato no navegador

Uma resposta JSON chegou e o código tentou ler um campo como texto. Se ele estiver ausente, for null ou contiver um número, tratar tudo como string pode esconder uma mudança no contrato da API. A solução não é inventar um valor padrão que faça a tela parecer correta: é decidir quais tipos são aceitos.

A unit CSCoder.JSON reúne três operações pequenas: TentarLerString, TentarLerInteiro e TentarLerBoolean. Ela usa apenas bibliotecas padrão do Delphi. O objetivo é reduzir repetição quando vários consumidores precisam do mesmo cuidado com tipos.

O contrato vem antes da conveniência

Cada função recebe um TJSONObject, o nome de um campo direto e uma saída por out. O retorno booleano indica se a leitura teve sucesso. Não há interpretação de caminhos como cliente.endereco.cep: esse texto seria procurado como o nome literal de um campo.

Função Aceita Não converte automaticamente
TentarLerString TJSONString, inclusive texto vazio Números, booleanos e null
TentarLerInteiro Número inteiro decimal literal no intervalo de Integer String numérica, fração e expoente
TentarLerBoolean Booleano JSON "true", 0 ou 1

Em uma falha, a saída fica vazia, zero ou False. Por isso, sempre confira o retorno da função: False pode ser um valor booleano lido com sucesso. Da mesma maneira, zero pode ser um inteiro legítimo e uma string vazia pode ser um texto válido.

A unit retorna False para objeto nil, campo ausente, null e tipo incorreto. Ela não distingue essas causas no retorno; se o consumidor precisar dessa distinção, examine a estrutura e produza um diagnóstico próprio. Não transforme a função em uma validação completa de qualquer contrato.

Uma leitura pequena, sem conversão silenciosa

A implementação de leitura de string é curta:

delphi
function TentarLerString(const Objeto: TJSONObject; const Campo: string;
  out Valor: string): Boolean;
var V: TJSONValue;
begin
  Valor := '';
  Result := False;
  if Objeto = nil then Exit;
  V := Objeto.GetValue(Campo);
  if not (V is TJSONString) then Exit;
  Valor := TJSONString(V).Value;
  Result := True;
end;

A função não usa Value em qualquer classe JSON para tornar uma entrada incompatível aparentemente válida. Ela primeiro confirma o tipo. TJSONString.Value entrega o texto da string, enquanto o chamador continua responsável por decidir se esse texto pode ser vazio ou precisa obedecer a outra regra.

Para números, o helper trabalha com Integer: verifica a representação decimal e usa TryStrToInt, sem arredondar uma fração. Um JSON como {"quantidade":1e2} contém um número válido, mas está fora do contrato estrito deste helper. Uma API que permite esse formato precisa de uma política numérica diferente.

Exemplo completo de utilização

O projeto abaixo foi compilado e executado. Ele mostra uma leitura booleana bem-sucedida cujo valor é False:

delphi
program ExemploJSON;
{$APPTYPE CONSOLE}
uses System.SysUtils, System.JSON, CSCoder.JSON;
var Raiz: TJSONValue; Obj: TJSONObject; Nome: string; Idade: Integer; Ativo: Boolean;
begin
 Raiz:=TJSONObject.ParseJSONValue('{"nome":"Ana","idade":25,"ativo":false}');
 try
  if not (Raiz is TJSONObject) then raise Exception.Create('Objeto esperado');
  Obj:=TJSONObject(Raiz);
  if TentarLerString(Obj,'nome',Nome) then Writeln('Nome: ',Nome);
  if TentarLerInteiro(Obj,'idade',Idade) then Writeln('Idade: ',Idade);
  if TentarLerBoolean(Obj,'ativo',Ativo) then Writeln('Ativo: ',BoolToStr(Ativo,True));
 finally Raiz.Free; end;
end.

A raiz pertence ao chamador e é liberada no finally. As funções devolvem valores, não referências para objetos da árvore JSON. Não libere o campo obtido por GetValue separadamente da raiz apenas para copiar seu texto. A documentação de System.JSON apresenta os tipos usados na árvore.

O helper não faz a requisição HTTP, não interpreta o texto JSON e não limita a resposta recebida. Essas responsabilidades continuam no consumidor. Também não altera a política do parser em relação a chaves duplicadas ou documentos muito grandes.

Quando o helper ajuda — e quando não ajuda

Em uma única leitura pequena, um if Valor is TJSONString pode ser mais direto. Introduzir outra unit apenas para esconder três linhas nem sempre compensa.

Quando diversas integrações repetem as mesmas verificações, uma função com contrato explícito pode evitar diferenças acidentais: uma tela aceita string numérica, outra não; uma conserva a saída antiga, outra limpa. Centralizar a decisão facilita revisar esses comportamentos.

O custo é administrar uma dependência e compreender seu contrato. Essa unit não deve virar o lugar de toda regra de negócio. Verificar que idade é um inteiro não determina se a idade é aceitável para uma operação específica.

Download, testes e próxima leitura

Baixar CSCoder.JSON.pas · Baixar unit e projeto de testes.

A unit foi compilada com DCC32 37.0, build 37.0.59082.6021, e passou por 28 verificações: tipos corretos e incorretos, ausência, null, objeto nil, limites de Integer e overflow. O ZIP inclui o projeto de console, a licença MIT e as instruções. Ler a licença completa.

Para observar a diferença em uma integração concreta, continue em Consulta de CEP no Delphi: com e sem helper JSON. As duas versões consultam o mesmo serviço e usam o mesmo contrato: o que muda é onde a leitura dos campos está implementada.

Experimento: falha não é valor vazio

  1. No laboratório JSON, selecione zero, False e string vazia.
  2. Compare success e value separadamente: esses valores podem ser leituras bem-sucedidas.
  3. Troque para ausente, null e tipo incorreto; espere success false.
  4. Compare 100, 1e2 e 100.0: só literal inteiro decimal atende ao helper estrito.
  5. Teste intervalo Integer, array e JSON malformado.

Saída esperada: zero válido retorna sucesso true e valor 0; ausência retorna sucesso false e valor 0. Demo web preserva literais; também rejeita chaves repetidas e profundidade acima de 32, limites adicionais próprios. Máximo 16 KiB; não executa Delphi nem transmite entradas.

Abrir projeto de exemplo ↗