Distinguir transporte, sintaxe JSON e validade dos campos
Tutorial · prática orientada · IntermediárioExceções, tipos JSON e noções de HTTP
Unit principal compilada e exercitada com DCC32 37.0, build 37.0.59082.6021. Referência editorial: Delphi 11.3 e 13.2; essas duas versões não foram verificadas individualmente.Documentação, instalação e limites de Fundamentos em seis units
Experimentar o contrato no navegador
Seu serviço devolveu HTTP 200 e a aplicação tentou ler nome. O campo não existia. O problema ilustra três verificações distintas: a requisição foi atendida, o conteúdo pode ser interpretado e a estrutura corresponde ao contrato que o consumidor espera.
Vamos implementar a terceira parte usando uma resposta fixa. Assim, é possível estudar o parser sem depender de uma rede disponível ou de uma API pública que pode mudar.
Escreva o contrato antes do parser
O contrato deste exercício exige um objeto com nome do tipo string, preenchido após remover espaços. Campos extras serão ignorados. A raiz não pode ser um array, e null não equivale a texto vazio.
{"nome":"Ana","ativo":true}JSON possui tipos próprios, como strings, números, objetos, arrays e null. Para intercâmbio entre sistemas, a especificação exige UTF-8. Isso não define os campos da sua API: esse contrato ainda precisa ser documentado. RFC 8259.
Valide e copie o dado necessário
Crie Api.Nomes.pas:
unit Api.Nomes;
interface
function LerNomeJSON(const Texto: string): string;
implementation
uses
System.SysUtils, System.JSON;
function LerNomeJSON(const Texto: string): string;
var
Raiz: TJSONValue;
Nome: TJSONValue;
begin
Raiz := TJSONObject.ParseJSONValue(Texto);
try
if not (Raiz is TJSONObject) then
raise EArgumentException.Create('Objeto JSON esperado');
Nome := TJSONObject(Raiz).GetValue('nome');
if not (Nome is TJSONString) then
raise EArgumentException.Create('nome deve ser uma string');
Result := Trim(TJSONString(Nome).Value);
if Result = '' then
raise EArgumentException.Create('nome não pode ser vazio');
finally
Raiz.Free;
end;
end;
end.O código libera a raiz criada pelo parser. Nome referencia um valor contido nessa árvore; não é um novo objeto que o consumidor precise liberar separadamente. O retorno é uma string copiada, que pode continuar sendo usada depois da destruição da árvore.
O comportamento de parsing e suas opções devem ser conferidos na referência de ParseJSONValue. A unit foi compilada e os casos da tabela passaram no projeto de verificações, incluindo JSON sintaticamente inválido.
Monte casos antes de integrar a rede
| Entrada | Expectativa |
|---|---|
{"nome":"Ana"} |
Retorna Ana |
{"nome":" Ana "} |
Retorna Ana |
{"nome":42} |
Rejeita o tipo |
{"nome":null} |
Rejeita o tipo |
{} |
Rejeita campo ausente |
[] |
Rejeita a raiz |
| Texto inválido | Rejeita ou propaga falha de parsing |
Teste também campos extras. Se sua API exige rejeitar chaves duplicadas ou limita o tamanho do documento, acrescente uma política explícita; o exemplo acima não implementa essas verificações. Para entrada não confiável, imponha limites antes de carregar uma resposta inteira em memória.
Conecte transporte e contrato em etapas
Quando integrar THTTPClient, defina timeouts e valide o status antes de interpretar um corpo de sucesso. Leia o tipo de conteúdo esperado e trate respostas sem corpo conforme o contrato. Um HTTP 204, por exemplo, não precisa ser um objeto JSON ausente por erro.
Não registre o corpo inteiro para diagnosticar qualquer falha: a resposta pode conter dados pessoais. Prefira contexto da operação, código HTTP e diagnóstico sanitizado.
Timeout não prova que nada aconteceu
Um servidor pode ter aplicado uma gravação antes de a conexão cair. Repetir a requisição pode duplicar a operação. A semântica de idempotência descreve o efeito pretendido de repetir uma mesma requisição; não autoriza repetição indiscriminada de toda operação. RFC 9110, seção 9.2.2.
Para uma escrita, siga o mecanismo previsto pela API, como uma chave de idempotência quando oferecida, e estabeleça como consultar o resultado de uma operação de desfecho incerto.
Experimento e próxima leitura
Crie os casos da tabela em um projeto de console e execute a função sem rede. Só então conecte o transporte. Quando surgir uma falha, você conseguirá dizer em qual etapa ela ocorreu.
Continue em Autenticação e proteção de tokens para analisar a credencial que acompanha a requisição.
Cinco cenários em fronteiras distintas
- No laboratório HTTP, compare 200 válido.
- 200 com corpo inválido falha na sintaxe.
- 204 não tem corpo para interpretar.
- 401 indica autenticação recusada.
- Timeout deixa desfecho remoto incerto: não repita escrita automaticamente.
Cada fixture explica a fronteira; nenhuma rede é acessada. Campos JSON pertencem à raiz; copie os valores e libere a raiz, não cada campo separadamente.
Uma resposta HTTP 200 garante que os dados estão corretos?
Compare três respostas: um objeto JSON válido, um JSON sem um campo obrigatório e um texto que não é JSON. Descreva em que etapa cada resposta deve ser rejeitada.
Ver uma pista para começar
O status HTTP descreve a requisição. Depois dele, valide o formato, os campos e os valores do contrato. Um status 200 não garante a validade dos dados.
Não precisa acertar de primeira. Observe o resultado e explique o que mudou.