How to Migrate from JSON Server v0 to v1: Complete Upgrade Guide
JSON Server v1 requires updating pagination parameters from _limit to _per_page, replacing _expand with _embed for relationships, removing manual numeric IDs in favor of auto-generated hex strings, and eliminating the --delay CLI flag in favor of browser DevTools throttling.
Upgrading from JSON Server version 0 to version 1 involves several breaking changes that affect how you structure API requests and handle data identification. While the core architecture remains a LowDB wrapper with an Express-like API, the migration impacts ID generation, query parameters, relationship loading, and latency simulation. This guide walks through the specific source code changes in typicode/json-server to ensure your client code works seamlessly with v1.
Breaking Changes in JSON Server v1
Auto-Generated String IDs Replace Manual Numeric IDs
In src/random-id.ts, JSON Server v1 implements a new ID generation strategy using Node.js crypto utilities:
// src/random-id.ts
import { randomBytes } from 'node:crypto'
export function randomId(): string {
return randomBytes(2).toString('hex')
}
The Service.create() method in src/service.ts (lines 45-51) automatically invokes this function when you POST new resources without an ID:
async create(name: string, data: Omit<Item, 'id'> = {}): Promise<Item | undefined> {
const items = this.#get(name)
if (items === undefined || !Array.isArray(items)) return
const item = { id: randomId(), ...data }
items.push(item)
await this.#db.write()
return item
}
Migration action: Remove id fields from your POST request bodies. The server now assigns 4-character hexadecimal strings (e.g., "a3f7") automatically, eliminating the need to track numeric sequences client-side.
Pagination Parameters Renamed from _limit to _per_page
The pagination logic in src/paginate.ts (lines 11-22) no longer recognizes the _limit query parameter. Instead, it validates _per_page for page sizing:
export function paginate<T>(items: T[], page: number, perPage: number): PaginationResult<T> {
const totalItems = items.length
const safePerPage = Number.isFinite(perPage) && perPage > 0 ? Math.floor(perPage) : 1
const pages = Math.max(1, Math.ceil(totalItems / safePerPage))
// ... calculates prev/next and slices results
}
In src/service.ts (lines 38-41), the find() method forwards these parameters directly:
if (opts.page !== undefined) {
return paginate(results, opts.page, opts.perPage ?? 10)
}
Migration action: Update all client requests to use _per_page instead of _limit when specifying page size, while keeping _page for the page number.
Relationship Embedding Changes from _expand to _embed
Relationship loading now uses the _embed query parameter instead of _expand. In src/service.ts (lines 28-34 and 96-104), the service processes embedding through the embed() helper function:
ensureArray(opts.embed).forEach((related) => {
results = results.map((item) => embed(this.#db, name, item, related))
})
This applies to both collection queries (find()) and single resource lookups (findById()).
Migration action: Replace all instances of _expand with _embed in your API calls to include nested related resources.
Removal of the --delay CLI Flag
The CLI entry point in src/bin.ts no longer registers a --delay flag for artificial latency. According to the README migration notes, this server-side delay simulation has been removed entirely.
Migration action: Remove --delay from your startup scripts. Simulate network latency using browser DevTools (Network tab → Throttling) or proxy tools instead of server configuration.
Code Migration Examples
Before: JSON Server v0 Patterns
# Start server
json-server db.json
# Pagination with _limit (v0)
curl "http://localhost:3000/posts?_page=1&_limit=5"
# Expand related comments (v0)
curl "http://localhost:3000/posts/1?_expand=comments"
# POST with manual numeric ID
curl -X POST -H "Content-Type: application/json" \
-d '{"id":2,"title":"New post"}' \
http://localhost:3000/posts
After: JSON Server v1 Patterns
# Start server (command unchanged)
json-server db.json
# Pagination with _per_page (v1)
curl "http://localhost:3000/posts?_page=1&_per_page=5"
# Embed related comments (v1)
curl "http://localhost:3000/posts/1?_embed=comments"
# POST without ID (v1 auto-generates hex string)
curl -X POST -H "Content-Type: application/json" \
-d '{"title":"New post"}' \
http://localhost:3000/posts
Summary
- String IDs: JSON Server v1 generates hexadecimal string IDs automatically via
randomId()insrc/random-id.ts; omit theidfield in POST requests. - Pagination syntax: Replace
_limitwith_per_pagein query strings, as implemented insrc/paginate.ts. - Relationship loading: Use
_embedinstead of_expandto include related data, processed insrc/service.ts. - Delay simulation: Remove the
--delayflag from CLI startup commands; use browser DevTools for network throttling instead.
Frequently Asked Questions
How do I handle existing numeric IDs when migrating to JSON Server v1?
JSON Server v1 maintains backward compatibility with existing data. If your db.json contains numeric IDs, they remain valid strings (numbers are valid JSON string values). However, all new resources created via POST will receive 4-character hex string IDs generated by the randomId() function. Keep existing IDs as-is, but update your client code to expect string IDs for new resources.
Why was the _limit parameter removed in favor of _per_page?
The _per_page parameter aligns with modern REST API conventions and provides clearer semantic meaning. According to the source code in src/paginate.ts, the parameter is explicitly validated as perPage rather than limit, making the API more self-documenting. Update your client libraries to construct URLs with _per_page to restore pagination functionality.
Can I still simulate network delays in JSON Server v1?
No, server-side delay simulation has been removed from the CLI. The src/bin.ts file no longer parses a --delay flag. To test how your application behaves under slow network conditions, use Chrome DevTools Network throttling, Firefox Network Monitor throttling, or tools like Charles Proxy or Clumsy to introduce latency between your client and the JSON Server instance.
What should I do if my client code expects numeric IDs?
Update your client-side data models to accept strings instead of numbers for the id field. Since src/service.ts uses randomBytes(2).toString('hex') to generate IDs like "a3f7" or "8b2e", any client-side validation expecting integers will fail. TypeScript users should update interfaces from id: number to id: string, and JavaScript consumers should remove numeric parsing or validation logic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →