Express Partial Response Middleware
raw JSON →express-partial-response is an Express.js middleware designed to filter parts of JSON responses based on a `fields` query-string parameter. It mimics the "Partial Response" feature found in Google APIs, allowing clients to request only a subset of data from an API endpoint, thereby reducing bandwidth and processing on the client side. The current stable version is 1.0.4. The project appears to be in a maintenance state, with no recent major updates mentioned, suggesting a stable and complete feature set rather than active development. Its core functionality is powered by the `json-mask` library, which handles the actual JSON object filtering according to the specified field syntax. This middleware differentiates itself by providing a direct, out-of-the-box integration for Express applications, simplifying the implementation of partial responses without requiring manual integration of `json-mask` into every route.
Common errors
error TypeError: app.use() requires a middleware function but got a Object ↓
partialResponse function to get the actual middleware. Correct usage is app.use(partialResponse()); or app.use(partialResponse({ options }));. error Response is not filtered as expected (or is empty) when using the 'fields' query parameter. ↓
fields query parameter against the json-mask syntax documentation. Common mistakes include typos, incorrect nesting parentheses, or missing commas. error ReferenceError: require is not defined (in an ESM context) ↓
import() (e.g., const partialResponse = await import('express-partial-response'); const middleware = partialResponse.default();) or a build tool that handles CJS-to-ESM conversion. Warnings
gotcha The syntax for the `fields` query parameter is handled by the underlying `json-mask` library. Developers must refer to `json-mask`'s documentation for complex filtering patterns, nested fields, and array handling, as `express-partial-response` simply passes the string. ↓
gotcha This middleware is designed exclusively for JSON responses. If applied to routes that return other content types (like HTML, plain text, or files) and `res.json()` is not eventually called, the middleware will have no effect or might lead to unexpected behavior. ↓
gotcha As a general principle with field filtering, ensure that the fields available for filtering do not inadvertently expose sensitive data that should otherwise be protected. While the middleware filters based on client input, the original data might contain sensitive fields that could be exposed if requested via a wildcard or an overly broad mask. The `json-mask` library itself does not offer mechanisms for field-level access control. ↓
gotcha This package is written in CommonJS (CJS) and does not officially support ES Modules (ESM) directly. Attempting to use `import` statements in an ESM project will lead to errors. ↓
Install
npm install express-partial-response yarn add express-partial-response pnpm add express-partial-response Imports
- partialResponse wrong
const { partialResponse } = require('express-partial-response');correctconst partialResponse = require('express-partial-response'); - partialResponse(options) wrong
app.use(partialResponse);correctapp.use(partialResponse({ query: 'filter' }));
Quickstart
const express = require('express');
const partialResponse = require('express-partial-response');
const app = express();
// Apply the partial response middleware globally
app.use(partialResponse({ query: 'fields' })); // Default query param is 'fields'
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
const users = [
{
id: '1',
firstName: 'Mohandas',
lastName: 'Gandhi',
email: 'm.gandhi@example.com',
addresses: [{ street: '123 Peace Rd', city: 'Ahimsa', country: 'India' }],
aliases: [
{ firstName: 'Mahatma', lastName: 'Gandhi' },
{ firstName: 'Bapu', title: 'Father of the Nation' }
],
secretInfo: 'Top Secret - Only for internal use'
},
{
id: '2',
firstName: 'Nelson',
lastName: 'Mandela',
email: 'n.mandela@example.com',
addresses: [{ street: '456 Freedom St', city: 'Ubuntu', country: 'South Africa' }],
aliases: [
{ firstName: 'Madiba', lastName: 'Mandela' }
],
secretInfo: 'Top Secret - Only for internal use'
}
];
const user = users.find(u => u.id === userId);
if (user) {
res.json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
});
app.get('/products', (req, res) => {
const products = [
{ id: 'a1', name: 'Laptop', price: 1200, category: 'Electronics', description: 'Powerful laptop', supplier: 'TechCorp' },
{ id: 'b2', name: 'Mouse', price: 25, category: 'Electronics', description: 'Wireless mouse', supplier: 'AccessoryCo' }
];
res.json(products);
});
const port = process.env.PORT ?? 4000;
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
console.log('\nTry these examples:');
console.log(`- Get user 1's first name and alias first names: curl 'http://localhost:${port}/users/1?fields=firstName,aliases(firstName)'`);
console.log(`- Get user 2's id and email: curl 'http://localhost:${port}/users/2?fields=id,email'`);
console.log(`- Get product names and prices: curl 'http://localhost:${port}/products?fields=name,price'`);
console.log(`- Get all fields for user 1 (no 'fields' param): curl 'http://localhost:${port}/users/1'`);
});