Skip to content

Parameter and body annotations

Most parameters need no annotation: the generator infers the location from the name and type (see parameter classification). Use the annotations on this page to rename a parameter, add a description, force a location, or document inputs for handlers that read the raw Request themselves.

Binds a method parameter to a path placeholder.

@Target({TargetKind.parameter})
class Path {
const Path({this.name, this.description, this.example});
final String? name;
final String? description;
final Object? example;
}

When to use: when the Dart parameter name differs from the {placeholder}, or to add a description. A parameter whose name already matches a placeholder is a path parameter without it.

Parameter Type Default Description
name String? Dart parameter name Placeholder name, without braces.
description String? null Parameter description in the document.
example Object? null Accepted but currently not emitted by the generator.

The value is parsed with coerce<T>() (String, int, double, num, bool, DateTime) and is always required: true. A value that does not parse is a 400.

Example

import 'package:gisila_doc/gisila_doc.dart';
@Get('/{userId}/posts')
Future<List<Post>> posts(
@Path(name: 'userId', description: 'Author id') int id,
PostService posts,
) => posts.byAuthor(id);

Binds a method parameter to a query-string key.

@Target({TargetKind.parameter})
class Query {
const Query({this.name, this.description, this.example});
}

When to use: to rename a query key (?page_size= to pageSize) or describe it. Primitive parameters that are not path placeholders are query parameters without it.

Parameter Type Default Description
name String? Dart parameter name Query key.
description String? null Parameter description.
example Object? null Accepted but currently not emitted.

The parameter is required when its type is non-nullable and it is not optional. An empty value (?page=) counts as missing for anything but String. Dart default values are not applied, so declare optional query parameters nullable and apply defaults in the method body.

Example

@Get('/')
Future<List<User>> list(
UserService users, {
@Query(name: 'page_size', description: 'Rows per page') int? pageSize,
}) => users.list(limit: pageSize);

Binds a method parameter to a request header.

@Target({TargetKind.parameter})
class Header {
const Header({this.name, this.description});
}

When to use: whenever you want a header as a parameter; headers are never inferred.

Parameter Type Default Description
name String? Dart parameter name Header name. Looked up lower-cased.
description String? null Parameter description.

The generated code assigns the raw header string with no parsing, so declare the parameter as String?. It is documented as required when the Dart type is non-nullable and not optional.

Example

@Post('/webhooks')
Future<void> hook(
WebhookEvent event,
@Header(name: 'X-Signature', description: 'HMAC of the body') String? signature,
) async { /* ... */ }

Marks a method parameter as the JSON request body.

@Target({TargetKind.parameter})
class Body {
const Body({
this.contentType = 'application/json',
this.required = true,
this.description,
});
}

When to use: when the body parameter would otherwise be classified differently, for example a Map<String, dynamic> you want as the body even though another parameter came first. The first unannotated non-primitive parameter is already treated as the body.

Parameter Type Default Description
contentType String 'application/json' Currently not used by the generator; the body is always read and documented as JSON.
required bool true Currently not used; requiredness comes from the parameter (required unless optional or nullable).
description String? null Currently not emitted.

To document a body with a description or another content type, use BodyDoc.

Example

@Put('/{id}/settings')
Future<void> saveSettings(String id, @Body() Map<String, dynamic> settings) async {
/* ... */
}

Documents a query parameter that the handler reads itself from request.url.queryParameters.

@Target({TargetKind.method})
class QueryDoc {
const QueryDoc(
this.name, {
this.type = String,
this.required = false,
this.description,
});
}

When to use: with the raw-Request style, where the method takes a Request and parses inputs itself, so the generator cannot see them. Stack one per parameter. It only affects the document; nothing is parsed or validated for you.

Parameter Type Default Description
name String required Query key.
type Type String Dart type used to derive the schema.
required bool false Parameter required.
description String? null Parameter description.

Example

@Get('/products')
@QueryDoc('offset', type: int)
@QueryDoc('limit', type: int)
@QueryDoc('search', description: 'Matches name or SKU')
Future<Response> listProducts(Request request) async {
final q = request.url.queryParameters;
// ...
return jsonResponse(body: await products.search(q['search']));
}

Documents the request body schema for a route.

@Target({TargetKind.method})
class BodyDoc {
const BodyDoc(
this.type, {
this.required = true,
this.description,
this.contentType = 'application/json',
});
}

When to use: when the method does not take a typed body or Form parameter (it reads the Request itself) but you still want the body documented, or when you need a description or a non-JSON content type in the document. Prefer the inline form, @Post('/x', body: BodyDoc(T)). A typed body or form parameter takes precedence over BodyDoc; a standalone @BodyDoc takes precedence over the inline body:.

Parameter Type Default Description
type Type required Class whose schema describes the body.
required bool true requestBody.required.
description String? null requestBody.description.
contentType String 'application/json' Media type key under content.

Example

@Post(
'/login',
summary: 'Log in',
body: BodyDoc(LoginRequest, description: 'Login credentials'),
responses: [Returns(statusCode: 200, bodyType: TokenResponse)],
)
Future<Response> login(Request request) async {
final json = await readJsonBody(request) as Map<String, dynamic>;
// ...
}

See also: Describe request and response models, How schemas are derived.