Skip to content

Formatters & Code

JSON to tRPC Router

tRPC router scaffold with Zod input — list, byId, create.

Runs in your browser
JSON · source
lines: 17chars: 261size: 261 B
tRPC router · result
lines: 34chars: 832size: 832 B
live

Understanding JSON → tRPC

End-to-end types, zero schema language.

What tRPC does that REST and GraphQL don't, and how a JSON sample scaffolds a router with input validation and inferred client types.

No schema, just TypeScript.

REST APIs have OpenAPI; GraphQL has SDL. tRPC has neither — the contract between client and server is the TypeScript types of the router itself. The client imports type AppRouter = typeof router and gets fully-typed calls: parameter types, return types, error types, all inferred. No code generation, no schema file, no runtime mismatch. The cost is that it only works when client and server are both TypeScript and can share types directly.

Procedures: query, mutation, subscription.

tRPC has three procedure types. query for reads (cached, idempotent); mutation for writes (not cached, invalidates); subscription for server-sent events. Each takes an optional input validator (typically a Zod schema) and returns whatever its handler returns. The shape of a router is a nested object literal whose leaves are procedures.

A worked router.

From a JSON sample { "id": 7, "email": "a@b.com", "name": "Q" } the codegen tool emits a scaffolded router: import { z } from "zod"; import { router, publicProcedure } from "./trpc"; export const userRouter = router({ list: publicProcedure.query(async () => { return []; }), byId: publicProcedure .input(z.object({ id: z.number().int().positive() })) .query(async ({ input }) => { /* fetch by id */ }), create: publicProcedure .input(z.object({ email: z.string().email(), name: z.string().min(1) })) .mutation(async ({ input }) => { /* insert */ }), }); Three procedures: list, byId, create. Inputs are Zod schemas; client types are inferred from these. The handler bodies are the only thing left to write.

Three procedures

list + byId + create

Stock CRUD shape; the user fills in the bodies.

userRouter = router({ list, byId, create })

= Typed API

Zod is the runtime gate.

tRPC's .input(schema) uses any validator that conforms to its { parse } interface — Zod is by far the most common. The schema runs at runtime on every request; bad input rejects with a 400 before the handler runs. The TypeScript types are inferred from the Zod schema too, so the same definition gives you compile-time client types and runtime validation. That's the trick that makes tRPC work without a separate schema file.

Why JSON-to-tRPC is structural, not semantic.

A JSON sample tells you the entity's shape — what to create / read / update. It can't tell you the procedure granularity, the access control rules, the audit requirements, or the batching strategy. Codegen scaffolds the stock CRUD shape; most real routers diverge by either combining procedures (a single upsert rather than separate create and update) or specialising them (a listForOrganisation with auth checks).

When tRPC isn't the answer.

tRPC requires that client and server share TypeScript types. That works for a Next or Remix app where you control both ends. It doesn't work for a public API consumed by third parties, mobile apps not written in TypeScript, or anything that might one day need to be polyglot. For those, fall back to REST + OpenAPI or GraphQL. tRPC is the right choice precisely when the shared-types invariant holds.

Frequently asked questions

Quick answers.

How does the tool handle data types?

The generator inspects the JSON values to determine types like `z.string()`, `z.number()`, and `z.boolean()`. Nested objects are converted into `z.object()` calls and arrays into `z.array()` structures.

Does this work with tRPC v10?

Yes. The output uses the `t.router` and `t.procedure` syntax standard in tRPC v10 and later versions.

Can I use the output with any database?

Yes. The generated code provides the router structure and validation logic, which you can then connect to Prisma, Drizzle, or any other database ORM within the procedure resolvers.

Is my JSON data secure?

Yes. The conversion logic runs locally in your browser using JavaScript. No data is sent to a server or stored in a database.

People also search for

Related tools

More in this room.

See all in Formatters & Code