Skip to content

Smart Coercion Plugin

Automatically converts values to match your schema types without requiring manual coercion logic.

WARNING

This plugin improves developer experience, but it adds runtime overhead. For performance sensitive applications or complex schemas, manual coercion in your validation layer is usually more efficient.

Installation

sh
npm install @orpc/json-schema@beta
sh
yarn add @orpc/json-schema@beta
sh
pnpm add @orpc/json-schema@beta
sh
bun add @orpc/json-schema@beta
sh
deno add npm:@orpc/json-schema@beta

Setup

Use SmartCoercionHandlerPlugin in your handler to coerce incoming request data to the expected .input schema:

ts
import { SmartCoercionHandlerPlugin } from '@orpc/json-schema'

const handler = new OpenAPIHandler(router, {
  plugins: [
    new SmartCoercionHandlerPlugin({
      converters: [
        new ZodToJsonSchemaConverter(),
        // Add other schema converters as needed
      ],
    })
  ]
})

Use SmartCoercionLinkPlugin in your link to coerce server responses to the expected .output or .errors schemas:

ts
import { SmartCoercionLinkPlugin } from '@orpc/json-schema'

const link = new OpenAPILink(contract, {
  plugins: [
    new SmartCoercionLinkPlugin(contract, {
      converters: [
        new ZodToJsonSchemaConverter(),
        // Add other schema converters as needed
      ],
    }),
  ]
})

INFO

This plugin relies on JSON Schema Converters to determine how values should be coerced. Configure the appropriate converter for each validation library you use. If a required converter is unavailable, it automatically falls back to Standard Json Schema conversion.

How It Works

The plugin coerces values safely by following these rules:

  1. Schema-driven: Converts only when the schema defines the target type
  2. Safe only: Converts only values with an unambiguous representation, such as '123' to 123
  3. Preserve original values: Leaves the original value unchanged when conversion would be unsafe
  4. Union-aware: Picks the best match for union types
  5. Deep conversion: Applies recursively inside nested objects and arrays

INFO

JSON Schema does not natively represent BigInt, Date, RegExp, URL, Set, or Map. For these types, oRPC relies on x-native-type metadata in your schema:

  • x-native-type: 'bigint' for BigInt
  • x-native-type: 'date' for Date
  • x-native-type: 'regexp' for RegExp
  • x-native-type: 'url' for URL
  • x-native-type: 'set' for Set
  • x-native-type: 'map' for Map

The built-in Standard Json Schema converter handles these cases. Because this metadata is outside the official JSON Schema specification, custom converters may need to add the appropriate x-native-type values explicitly.

Conversion Rules

String → Boolean

Supports these specific string values, case-insensitively:

  • 'true', 'on'true
  • 'false', 'off'false

INFO

HTML <input type="checkbox"> elements commonly submit 'on' or 'off', so this conversion is especially useful for form handling.

String → Number

Supports valid numeric strings:

  • '123'123
  • '3.14'3.14

String/Number → BigInt

Supports valid numeric strings or numbers:

  • '12345678901234567890'12345678901234567890n
  • 1234567890123456789012345678901234567890n

String → Date

Supports ISO date and datetime strings:

  • '2023-10-01'new Date('2023-10-01')
  • '2020-01-01T06:15'new Date('2020-01-01T06:15')
  • '2020-01-01T06:15Z'new Date('2020-01-01T06:15Z')
  • '2020-01-01T06:15:00Z'new Date('2020-01-01T06:15:00Z')
  • '2020-01-01T06:15:00.123Z'new Date('2020-01-01T06:15:00.123Z')

String → RegExp

Supports valid regular expression strings:

  • '/^\\d+$/i'new RegExp('^\\d+$', 'i')
  • '/abc/'new RegExp('abc')

String → URL

Supports valid URL strings:

  • 'https://example.com'new URL('https://example.com')

Array → Set

Supports arrays of unique values:

  • ['apple', 'banana']new Set(['apple', 'banana'])

Array → Object

Converts arrays into objects with numeric keys:

  • ['apple', 'banana']{ 0: 'apple', 1: 'banana' }

INFO

This is particularly useful for Bracket Notation when you need objects with numeric keys.

Array → Map

Supports arrays of key-value pairs with unique keys:

  • [['key1', 'value1'], ['key2', 'value2']]new Map([['key1', 'value1'], ['key2', 'value2']])

Advanced Usage

You can also use this plugin in guides such as Expanding Type Support for OpenAPI Link.

Learn More

For implementation details, see the SmartCoercionHandlerPlugin source code or the SmartCoercionLinkPlugin source code.

Released under the MIT License.