Skip to content

Parsing Query Parameters

To parse and validate JSON:API query strings (e.g. from a URL or request), use the createQueryParser function from @jsonapi-serde/server/request. It supports structured and typed parsing of:

  • include
  • fields
  • sort
  • filter
  • page

Usage Example

ts
import { createQueryParser } from "@jsonapi-serde/server/request";
import { z } from "zod/v4";

// Create a parser for a specific resource
const parseArticleQuery = createQueryParser({
    include: {
        allowed: ["author", "comments.author"],
    },
    sort: {
        allowed: ["title", "createdAt"],
        multiple: false,
    },
    fields: {
        allowed: {
            articles: ["title", "body"],
            users: ["name"],
        },
    },
    filter: z.object({
        published: z.enum(["true", "false"]),
    }),
    page: z.object({
        number: z.coerce.number().int().min(0),
        size: z.coerce.number().int().min(1),
    }),
});

// Parse a query string
const query = parseArticleQuery("include=comments.author&sort=-createdAt&page[number]=1&page[size]=10");

// Access parsed and validated values
console.log(query.include); // ["comments.author"]
console.log(query.sort);    // [{ field: "createdAt", order: "desc" }]
console.log(query.fields);  // { articles: ["title", "body"], users: ["name"] }
console.log(query.filter);  // { published: "true" }
console.log(query.page);    // { number: "1", size: "10" }

NOTE

Returned results and allowed default values are inferred from the list of allowed values if possible. This works great when you define the arrays right in the createQueryParser call, but fails if you define them in a variable outside.

In that case you need to mark the variable as const in order to get proper type inference:

ts
const allowedInclude = ["author", "comments.author"] as const;

const parseArticleQuery = createQueryParser({
    include: { allowed: allowedInclude }
});

Type-safe Result

The return value is fully typed:

ts
type ParseQueryResult = {
    include: ("author" | "comments" | "comments.author")[];
    sort: { field: "title" | "createdAt"; order: "asc" | "desc" }[];
    fields: {
        articles?: ("title" | "body")[];
        users?: ("name")[];
    };
    filter: { published: "true" | "false" };
    page: { number: number; size: number };
};

Notes

  • If a query parameter is omitted, defaults (if defined) will be applied.
  • Invalid paths, field names, or values will throw a ZodValidationError, which includes precise error metadata.
  • Omitting an option for a query parameter will forbid the client from supplying that value.