Repository navigation
objetos
Home > Servidor > Objetos no corpo 🚧
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: intermediário
Em uma frase: em vez de ler params um a um, a rota recebe o corpo já convertido num
objeto seu, validado, e responde com um objeto no formato que o cliente pediu
(Accept).
Você vai precisar: o pacote RALModuleObjectsPackage.
Qualquer classe com propriedades published. Descenda de TRALObject (um TPersistent
com construtor virtual) para o RAL chamar o seu Create e criar o que a classe possui:
type
TItem = class(TCollectionItem)
published
property Produto: string ...;
property Qtd: Integer ...;
end;
TPedido = class(TRALObject)
public
constructor Create; override; // cria FItens e FEndereco
destructor Destroy; override;
published
property Id: Int64 ...;
property Cliente: string ...;
property Criado: TDateTime ...; // ISO 8601
property Cores: TCores ...; // conjunto -> ["azul","verde"]
property Endereco: TEndereco read FEndereco; // objeto aninhado
property Itens: TCollection read FItens; // array
property Obs: TStrings read FObs; // array de textos
end;
initialization
RALRegisterObjectClass(TPedido); // para achar a classe pelo nomeTambém viram JSON: TStream (base64), TDataSet (array de registros) e listas
TObjectList registradas com RALRegisterListClass(TMinhaLista, TItem). Com RTTI
estendida (Delphi 2010+), TObjectList<T>, records e arrays também
(TRALObjectRTTI.ToText<T> / FromText<T>).
Server.CreateObjectRoute('pedidos', 'TPedido', Salvar).Allow([amPOST]);
procedure TForm1.Salvar(ARequest: TRALRequest; AResponse: TRALResponse; ABody: TObject);
var
vPedido: TPedido;
begin
vPedido := TPedido(ABody); // lido, validado; o RAL libera depois
...
RALAnswerObject(ARequest, AResponse, HTTP_Created, vPedido);
end;No Object Inspector: BodyClass e o evento OnReplyObject da rota. Corpo ilegível
(JSON quebrado) é 400; tipo que nenhum formatador lê é 415; regra quebrada é
422 (validação), sempre em application/problem+json.
Sem rota de objeto, as mesmas peças avulsas: RALReadBody(ARequest, Obj),
RALReadParams(ARequest, Obj) (query, path, cabeçalho e campos pelo nome da
propriedade) e RALAnswerObject.
| tipo | lê | escreve |
|---|---|---|
application/json (e *+json) |
sim | sim (padrão) |
application/x-www-form-urlencoded, multipart/form-data
|
sim | urlencoded |
text/csv |
uma coleção | coleção, lista, dataset |
application/yaml |
não | sim |
Ao responder vale o Accept com q= (q=0 recusa um tipo); ninguém serve, 406.
Um formatador seu herda de TRALObjectFormatter e entra com RALRegisterFormatter.
RALPreferredLanguage(ARequest.GetHeader('Accept-Language'), ['pt-BR', 'en']) escolhe o
idioma.
RALObjectSettings.JSON (ou o componente TRALObjectSettings): Naming (onAsIs,
onCamel → valorTotal, onSnake → valor_total, onKebab, onLower), EnumAs,
DateFormat (ISO local, ISO UTC, Unix), SkipNil, SkipDefault, IgnoreUnknown,
MaxDepth (corta ciclos), NullAs, ValidationStatus (422) e UnreadableStatus (400).
RALRegisterPropertyName(TClasse, 'Tipo', 'type') fixa um nome; com atributos (Delphi
2010+) [JSONName('type')] e [JSONIgnore] fazem o mesmo.
Api := TRALObjectClient.Create(Cliente); // Cliente: um TRALClient
if Api.Post('/pedidos', Pedido, Resposta) = 201 then ...
Api.Get('/pedidos/7', Pedido); // lê a resposta 2xx no objetoLastText guarda o corpo da última resposta (o problem+json de um erro). Para
descrever a API como interface, veja controllers.
ralopenapi petstore.json PetStore.pasGera uma unidade com uma classe TRALObject por components/schemas (com allOf como
herança, arrays de referência como listas registradas, os nomes da API registrados) e um
cliente com um método por operação. Lê JSON (OpenAPI 3.0 e 3.1); oneOf/anyOf viram
texto. Em código: RALOpenAPIToPascal(Texto, RALOpenAPIOptions('MinhaUnit')).
Uma rota com BodyClass ou ResponseClass aparece no Swagger com o esquema da classe
em components/schemas (as regras de validação viram required, maxLength,
pattern...), e os 400/422. O módulo Swagger também serve swagger.yaml.
| sintoma | causa |
|---|---|
| propriedades aninhadas nil, AV no handler | a classe não descende de TRALObject (o Create dela não roda) |
| 500 "BodyClass ... não está registrada" | falta RALRegisterObjectClass (ou RegisterClass) |
| 500 "RALModuleObjectsPackage não está ligado" | a unit RALObjectBinding não está no projeto |
| lista vazia no JSON |
TObjectList sem RALRegisterListClass
|
| datas uma hora fora |
DateFormat diferente dos dois lados; ISO com offset é o padrão |
Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- Swagger e Postman
- Servidor SOAP 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar