Body
In jin-frame, when you declare a class field with the @Body() decorator, the field value is serialized into the HTTP Request Body and included in the request. It is mainly used for POST, PUT, and PATCH requests, with JSON serialization supported by default.
Quick Example
@Post({ host: 'https://api.example.com', path: '/users' })
export class CreateUserFrame extends JinFrame {
@Body() declare readonly username: string;
@Body() declare readonly age?: number;
@Body() declare readonly tags?: string[];
@Body() declare readonly isAdmin?: boolean;
}
// Execute
const frame = CreateUserFrame.of({ username: 'pikachu', age: 7, tags: ['red', 'blue'], isAdmin: false });
const reply = await frame.execute();
console.log(reply.config.data);
// { "username": "pikachu", "age": 7, "tags": ["red","blue"], "isAdmin": false }Structure Definition
@Body() defines the body object at the field level. For example, consider the following type:
interface IamBody {
name: string;
age: number;
}When using @Body(), you define fields separately as follows:
@Post({ host: 'https://api.someapi.com', path: '/api/some/path' })
class PostFrameExample extends JinFrame {
@Body()
declare public readonly name: string;
@Body()
declare public readonly age: number;
}Here, the properties of IamBody (name, age) are declared individually with @Body. If you want to handle the entire object as a single field, you should use @ObjectBody instead.
Body vs ObjectBody
| Aspect | @Body | @ObjectBody |
|---|---|---|
| Declaration | Define each field separately | Define the whole object as a single field |
| Example | @Body() declare readonly name: string; | @ObjectBody() declare readonly user: User; |
| Serialization | Multiple fields merged into the Body | Serializes the declared object as-is |
| Use Cases | Simple field-based API requests | Pass DTOs or interfaces as the body directly |
Supported Types & Serialization
Types supported by @Body() and their JSON-serialized forms:
| Type | Example value | Serialized form |
|---|---|---|
string | 'pikachu' | "pikachu" |
number | 2 | 2 |
boolean | true | true |
string[] | ['a','b'] | ["a","b"] |
number[] | [1,2,4] | [1,2,4] |
object | { key: "value" } | { "key": "value" } |
undefined / null | undefined/null | omitted (key not created) |
undefined/nullvalues are omitted by default.- Arrays and objects are serialized directly as JSON.
Nested Objects
Nested objects are also supported.
@Post({ host: 'https://api.example.com', path: '/users' })
export class NestedBodyFrame extends JinFrame {
@Body() declare readonly profile: { name: string; age: number };
@Body() declare readonly settings?: { theme: string; notifications: boolean };
}
const reply = await NestedBodyFrame.of({
profile: { name: 'pikachu', age: 7 },
settings: { theme: 'dark', notifications: true },
}).execute();
// Body → { "profile": { "name": "pikachu", "age": 7 }, "settings": { "theme": "dark", "notifications": true } }Array Options
Arrays are serialized as JSON arrays. Unlike query strings, there is no need for comma or bitwise options.
@Post({ host: 'https://api.example.com', path: '/batch' })
export class ArrayBodyFrame extends JinFrame {
@Body() declare readonly ids: number[];
}
const reply = await ArrayBodyFrame.of({ ids: [1, 2, 3] }).execute();
// Body → { "ids": [1,2,3] }Optional Fields
If no value is provided, the key is omitted from the body.
@Post({ host: 'https://api.example.com', path: '/users' })
export class OptionalBodyFrame extends JinFrame {
@Body() declare readonly username: string;
@Body() declare readonly nickname?: string;
}
const reply = await OptionalBodyFrame.of({ username: 'pikachu' }).execute();
// Body → { "username": "pikachu" }Combining with Params & Headers
@Post({ host: 'https://api.example.com', path: '/orgs/:orgId/users' })
export class CreateUserInOrgFrame extends JinFrame {
@Param() declare readonly orgId: string;
@Header() declare readonly Authorization: string;
@Body() declare readonly username: string;
@Body() declare readonly age: number;
}
const reply = await CreateUserInOrgFrame.of({
orgId: 'acme',
Authorization: 'Bearer token',
username: 'pikachu',
age: 7,
}).execute();
// POST /orgs/acme/users
// Headers: { Authorization: "Bearer token" }
// Body: { "username": "pikachu", "age": 7 }Debugging Tip
Before sending a request, you can check the final body data using frame.getData('body').
const frame = CreateUserFrame.of({ username: 'pikachu', age: 7 });
const req = frame.request();
console.log(frame.getData('body')); // { username: 'pikachu', age: 7 }
console.log(req.data); // Final serialized body