How JSON Server Handles Relationships Between Collections: The Complete Guide to `_embed`
JSON Server handles relationships between collections by treating them as embedded resources that you request using the _embed query parameter, which triggers automatic foreign key resolution and merges related data directly into the response objects.
JSON Server provides a full fake REST API from a simple JSON file, but real-world applications require modeling relationships between collections. Understanding how JSON Server relationships between collections work is essential for designing clean APIs that handle one-to-many and many-to-one associations without writing custom backend code.
Understanding the _embed Query Parameter for JSON Server Relationships
JSON Server exposes relationships through the _embed query parameter, a convention introduced in version 1 to replace the earlier _expand syntax. When you append _embed=relatedCollection to a request, the server intercepts this parameter and triggers the embedding logic that resolves foreign key references.
According to the source code documentation in README.md (lines 258-261), this change to _embed makes the API intention explicit: you are embedding child or parent resources directly into the requested entity rather than expanding references.
How JSON Server Resolves Relationships Under the Hood
The relationship resolution happens across three main components in the codebase: the request parser, the service layer, and the embed helper.
Parsing the Request in src/app.ts
When a request hits the server, parseListParams in src/app.ts (lines 64-66) extracts the _embed value from the query string. This function parses the comma-separated list of related collections and passes them as an array to the service layer.
Service Layer Processing in src/service.ts
The Service.find and Service.findById methods in src/service.ts (lines 28-32) receive the embed list and iterate over each requested resource. For every relationship, they invoke the internal embed helper, passing the parent item, the related collection name, and the database instance.
The embed Helper and Foreign Key Resolution
The core logic resides in the embed function within src/service.ts (lines 23-47). This function uses the inflection library to detect relationship cardinality by checking if the related name is singular or plural:
-
Many-to-one (singular related name): The function searches the related collection for a record where
idmatches<related>Idon the main item. For example, a comment withpostId: 1embeds the post withid: 1. -
One-to-many (plural related name): The function gathers all records from the related collection where the foreign key
<parent>Idequals the main item'sid. For example, a post withid: 1embeds all comments wherepostId: 1.
The resulting related object or array is merged onto the original item under a property named after the related collection, then stored in res.locals['data'] for final JSON serialization.
Practical Examples of JSON Server Relationships
One-to-Many Relationship: Posts and Comments
To fetch posts with their associated comments embedded, use the plural form of the related collection:
GET /posts?_embed=comments
JSON Server returns:
[
{
"id": "1",
"title": "Hello World",
"comments": [
{ "id": "101", "postId": "1", "body": "Great post!" },
{ "id": "102", "postId": "1", "body": "Thanks for sharing." }
]
},
{ "id": "2", "title": "Another Post", "comments": [] }
]
Many-to-One Relationship: Comments and Posts
To fetch a comment with its parent post embedded, use the singular form:
GET /comments?_embed=post
Here, JSON Server detects the singular post, looks for a postId field on the comment, and embeds the matching post record.
Programmatic API Usage
When using JSON Server as a module, the same embedding logic applies through the service layer:
import { Low } from 'lowdb'
import { createApp } from './src/app.js'
const db = await new Low('db.json')
await db.read()
const app = createApp(db)
// Embedding works for both collection queries and single-item lookups
app.get('/posts', (req, res) => { /* _embed handled automatically */ })
app.get('/posts/:id', (req, res) => { /* _embed handled automatically */ })
Summary
- JSON Server handles relationships between collections through the
_embedquery parameter, which triggers automatic foreign key resolution. - The
parseListParamsfunction insrc/app.tsextracts embedding instructions from the request. - The
embedhelper insrc/service.tsuses theinflectionlibrary to distinguish between one-to-many (plural) and many-to-one (singular) relationships. - Foreign keys follow the convention
<parent>Idfor one-to-many and<related>Idfor many-to-one associations. - Embedded data is merged into the response object and stored in
res.locals['data']before JSON serialization.
Frequently Asked Questions
How do I query multiple relationships at once in JSON Server?
You can embed multiple collections by passing a comma-separated list to the _embed parameter. For example, GET /posts?_embed=comments,authors returns posts with both related comments and author objects merged into each post record. The service layer iterates over each value in the array and resolves the foreign keys independently.
What is the difference between _embed and the old _expand parameter?
JSON Server replaced _expand with _embed in version 1 to make the API more explicit. While _expand implied expanding a reference, _embed clearly indicates that you are embedding related resources directly into the response object. The underlying functionality remains similar, but _embed is the current standard as documented in README.md (lines 258-261).
How does JSON Server determine if a relationship is one-to-many or many-to-one?
The embed function in src/service.ts uses the inflection library to check if the requested resource name is singular or plural. A singular name (e.g., post) triggers a many-to-one lookup using <resource>Id on the parent item. A plural name (e.g., comments) triggers a one-to-many lookup using <parent>Id on the related items.
Can I use nested embedding to fetch relationships of relationships?
Standard JSON Server does not support automatic deep embedding through chained _embed parameters (e.g., _embed=comments.author). You can only embed direct relationships of the requested resource. For nested data, you must make separate requests or customize the database adapter to pre-compute nested structures before JSON Server processes the request.
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 →