Objeto de Transferência de Dados (DTO)
Vaden utiliza o conceito de DTOs (Objetos de Transferência de Dados) para transportar dados com segurança entre cliente e servidor. Os DTOs são integrados ao sistema de serialização chamado DSON, que lida com a conversão de objetos para e de JSON.
Anotação @DTO()
Para definir um DTO no Vaden, anote a classe com @DTO(). Isso marca a classe para geração de código para que o Vaden possa lidar com:
- Conversão automática de fromJson e toJson.
- Validação de entrada (via mixin Validator).
- Geração de esquema para OpenAPI.
()
class Credentials with Validator<Credentials> {
final String username;
final String password;
Credentials(this.username, this.password);
static Credentials fromJson(Map<String, dynamic> json) {
return Credentials(json['username'], json['password']);
}
LucidValidator<Credentials> validate(ValidatorBuilder<Credentials> builder) {
return builder
.ruleFor((c) => c.username, key: 'username').notEmpty()
.ruleFor((c) => c.password, key: 'password').minLength(6);
}
}
Além disso, você pode retornar um DTO diretamente de um método do controlador em vez de um Response. O Vaden irá serializá-lo automaticamente para JSON:
('/me')
UserProfile getProfile() => UserProfile('Alice');
Isso torna o controlador mais limpo, mantendo ainda um response adequado do tipo application/json.
Desserialização com @Body()
Quando um método do controlador usa @Body(), o Vaden irá:
- Ler o corpo JSON da requisição.
- Procurar o
@DTO()correspondente. - Desserializar os dados usando DSON.
- Opcionalmente validar o objeto antes de passá-lo para o seu método.
('/login')
String login(() Credentials credentials) {
return Response.ok(credentials.username);
}
Apenas classes com @DTO() são permitidas em parâmetros @Body().
DSON
DSON é o serializador automático do Vaden. É responsável por:
- Converter DTOs de JSON (
fromJson<T>()). - Converter objetos para JSON (
toJson<T>()). - Gerar esquemas OpenAPI.
Você pode injetá-lo em qualquer lugar:
()
class DebugService {
final DSON dson;
DebugController(this.dson);
String serializeCredentials( Map<String, dynamic> body) {
final dto = dson.fromJson<Credentials>(body);
return Response.ok(dson.toJson(dto));
}
}
Benefícios
- Não é necessário escrever serializadores boilerplate.
- Tratamento de erros limpo via validação.
- Totalmente tipado e preparado para OpenAPI.
Ao usar @DTO() e DSON juntos, o Vaden garante uma troca de dados confiável e limpa entre cliente e servidor.
Chave JSON (@JsonKey)
Se você quiser usar uma chave diferente no JSON do que o nome do campo, utilize @JsonKey():
()
class Credenciais {
('user_name')
final String username;
final String password;
Credenciais(this.username, this.password);
}
Campos opcionais sem tornar o tipo anulável
Por padrão, todo campo não anulável (sem ?) aparece como obrigatório no schema OpenAPI. Em alguns casos você quer manter o campo não anulável internamente (sempre populado depois que o objeto é criado), mas permitir que o cliente não o envie na requisição.
Use @JsonKey('nome', required: false) para tornar o campo opcional no OpenAPI mesmo sendo não-nullable em Dart:
()
class UserProfile {
final String id; // obrigatório (default)
('display_name', required: false)
final String displayName; // opcional no payload
final String? bio; // opcional por ser anulável
UserProfile({
required this.id,
required this.displayName,
this.bio,
});
}
Schema OpenAPI (simplificado):
{
"type": "object",
"properties": {
"id": { "type": "string" },
"display_name": { "type": "string" },
"bio": { "type": "string" }
},
"required": ["id"]
}
Resumo:
- Não anulável +
@JsonKey(required: false)→ opcional - Não anulável sem anotação → obrigatório
- Anulável (
Tipo?) → opcional - Mantém a robustez do modelo interno enquanto flexibiliza a entrada do cliente.