Skip to content
oRPC
Esc
navigateopen⌘Jpreview
On this page

OpenAPI Serializer

OpenAPI Serializers handle one-way serialization to JSON-friendly formats. They let you partially support complex data types beyond plain JSON, such as Date, BigInt, Set, and even custom classes.

Supported Data Types

OpenAPISerializer supports the following types by default:

Type Handler key Serialized Notes
string
number
NaN nan null
boolean
null
undefined undefined null Ignore undefined properties
Date date ISO String, null
BigInt bigint string
RegExp regexp string
URL url string
Record (object) toJSON methods are ignored
Array
Set set array
Map map array
Blob Unsupported in AsyncIteratorObject
File Unsupported in AsyncIteratorObject
AsyncIteratorObject Only at the root level
ReadableStream<Uint8Array> Only at the root level

Limitations

OpenAPI Serializers are designed for one-way serialization to JSON-friendly formats. For example, a Date is serialized to an ISO string and remains a string after deserialization unless you add custom logic or plugins.

In complex cases like mixed files with other data or nested structures in query strings, OpenAPI Serializer might use bracket notation to represent nested data, which has its own limitations. See Bracket Notation Limitations for details.

Custom Serializers

Add custom handlers with unique keys to support additional types, or reuse a built-in key to override the default behavior.

import { class OpenAPISerializer
Handles one-way serialization of oRPC payloads into JSON-friendly formats, partially supporting complex data types beyond plain JSON such as `Date`, `BigInt`, and `Set`.
@see{@link https://orpc.dev/docs/openapi/serializer OpenAPI Serializer}
OpenAPISerializer
} from '@orpc/openapi'
const const serializer: OpenAPISerializerserializer = new new OpenAPISerializer({ bracketNotation, serialize, ...options }?: OpenAPISerializerOptions): OpenAPISerializer
Handles one-way serialization of oRPC payloads into JSON-friendly formats, partially supporting complex data types beyond plain JSON such as `Date`, `BigInt`, and `Set`.
@see{@link https://orpc.dev/docs/openapi/serializer OpenAPI Serializer}
OpenAPISerializer
({
OpenAPIJsonSerializerOptions.handlers?: Record<string, OpenAPIJsonSerializerHandler | undefined> | undefined
Extend or override the built-in type handlers used during serialization. Each key is a unique type identifier (e.g. `"date"`, `"bigint"`) and maps to a handler that defines how to detect and serialize values of that type. **Extending:** Add new keys to support custom types: ```ts handlers: { buffer: { condition: (v) => v instanceof Buffer, serialize: (v: Buffer) => v.toString('base64'), isTerminal: true, } } ``` **Overriding:** Use an existing key to replace a built-in handler: ```ts handlers: { date: { condition: (v) => v instanceof Date, serialize: (v: Date) => v.getTime(), isTerminal: true, } } ``` **Disabling:** Set a key to `undefined` to remove a built-in handler: ```ts handlers: { regexp: undefined } ``` Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
handlers
: {
person: {
    condition: (v: unknown) => v is Person;
    serialize: (v: Person) => {
        name: string;
        age: number;
    };
}
person
: { // <- add support for Person
OpenAPIJsonSerializerHandler.condition(value: unknown): booleancondition: v: unknownv => v: unknownv instanceof class PersonPerson, OpenAPIJsonSerializerHandler.serialize(value: any): unknownserialize: (v: Personv: class PersonPerson) => ({ name: stringname: v: Personv.Person.name: stringname, age: numberage: v: Personv.Person.age: numberage }), },
date: {
    condition: (v: unknown) => v is Date;
    serialize: (v: Date) => number;
}
date
: { // <- replace the default Date handler
OpenAPIJsonSerializerHandler.condition(value: unknown): booleancondition: v: unknownv => v: unknownv instanceof var Date: DateConstructor
Enables basic storage and retrieval of dates and times.
Date
,
OpenAPIJsonSerializerHandler.serialize(value: any): unknownserialize: (v: Datev: Date) => v: Datev.Date.getTime(): number
Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
getTime
(),
}, }, })

Serialization Format

In most cases, serialized data is JSON-serializable.

{
  "name": "John",
  "age": 30,
  "createdAt": "2024-01-01T00:00:00.000Z"
}

With Files

If the data includes nested Blob or File, the serializer returns a FormData object using Bracket Notation. Non-file values are converted to strings, and null or undefined fields are omitted.

const form = new FormData()

form.append('name', 'Earth')
form.append('thumbnail', new Blob([''], { type: 'image/png' }))
form.append('images[0]', new Blob([''], { type: 'image/png' }))
form.append('createdAt', '2022-01-01T00:00:00.000Z')

Direct File

If the entire data is a single Blob or File, it can be sent as-is without wrapping in FormData.

HTTP/1.1 200 OK
Content-Type: image/png
Content-Disposition: attachment; filename="earth.png"
Content-Length: 12345
Standard-Server: file

<binary data>

AsyncIteratorObject

When the output is an AsyncIteratorObject, it is sent as a Server-Sent Events stream. Each event contains one serialized chunk of data.

HTTP/1.1 200 OK
Content-Type: text/event-stream

event: message
data: {"name":"John","createdAt":"2024-01-01T00:00:00.000Z"}

event: message
data: {"name":"Jane","createdAt":"2024-01-02T00:00:00.000Z"}

ReadableStream<Uint8Array>

A ReadableStream<Uint8Array> is passed through as-is and streamed as binary data.

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Standard-Server: octet-stream

<binary chunk 1>
<binary chunk 2>

Learn More

The serializer is a small, self-contained module, making it easy to understand. To explore its behavior in detail, see the source code.

Last updated on August 6, 2026

Was this page helpful?