@pas7/nestjs-strict-json is a strict JSON parser for NestJS, Express, and Fastify.
π Read our article: Understanding JSON Security Vulnerabilities and How We Solve Them - deep dive into the problems this package solves.
It blocks dangerous and ambiguous payloads at parser level:
- duplicate JSON keys
- prototype pollution keys (
__proto__,constructor,prototype) - excessive JSON depth (DoS-style payloads)
- disallowed key paths (whitelist/blacklist)
If you need secure JSON parsing in Node.js APIs, this package is built for that exact use case.
- β 12.8x faster parsing - optimized from 80.71ms to 6.30ms per operation
- β 85% less memory - reduced peak heap from 146MB to 21MB
- β Only 18% slower than native JSON.parse (was 24x slower)
- β Validator caching - 40-45% faster validation with LRU cache
- β
Memory leak fixed - cleanup interval now properly disposed with
shutdownCacheManager() - β Streaming duplicate validation - correctly detects duplicate keys at all nesting levels
shutdownCacheManager()- graceful shutdown of cleanup intervalresetCacheManager()- full reset for testingisCleanupIntervalRunning()- diagnostics for interval stategetCachedValidator()- get or create cached validatorclearValidatorCache()- clear validator cachegetValidatorCacheSize()- get cache size
- β Added 63 new tests (cache: 13, streaming: 32, validation: 18)
- β Total: 551 tests passing
- Security first: parser-level rejection of duplicate keys and prototype pollution attempts.
- Production ready: works with NestJS, vanilla Express, and vanilla Fastify.
- Performance controls: cache, lazy mode, streaming threshold, fast path.
- Typed and explicit errors: stable error codes for monitoring and incident response.
| Scenario | v0.4.x Baseline | v0.5.0 Optimized | Improvement |
|---|---|---|---|
| Large JSON (1MB) | 80.71ms/op | 6.30ms/op | 12.8x faster |
| Memory (Peak Heap) | 146.61MB | 21.03MB | 85% less |
| vs Native JSON.parse | 24x slower | 1.18x slower | 95% closer |
Latest local benchmark (2026-02-07, payload ~1.24 MB, 10,000 users):
| Implementation | Avg ms/op | Peak heap delta (MB) | Retained heap (MB) |
|---|---|---|---|
Native JSON.parse |
3.7878 | 9.62 | -0.01 |
jsonc-parser + JSON.parse |
21.4828 | 49.11 | 0.00 |
@pas7 strict (baseline) |
76.1405 | 253.60 | 0.00 |
@pas7 strict (optimized) |
3.2743 | 61.80 | -0.00 |
Key takeaways:
@pas7 strict (optimized)was faster than native in this run.@pas7 strict (optimized)was much faster thanjsonc-parser + JSON.parse.- Security checks and optimization profile significantly change results, so compare by scenario.
Reproduce:
npm run bench:compare| Capability | Native JSON.parse |
express.json() / default parsers |
@pas7/nestjs-strict-json |
|---|---|---|---|
| Duplicate key rejection | No | No | Yes |
| Prototype pollution key blocking | No | No | Yes |
| Max depth enforcement | No | No | Yes |
| Key whitelist/blacklist | No | No | Yes |
| Unified behavior across Nest/Express/Fastify | No | Partial | Yes |
| Structured parser error codes | No | Limited | Yes |
| Implementation | Avg ms/op (1MB) | Peak Heap (MB) | Relative Speed |
|---|---|---|---|
| Native JSON.parse | 5.36 | 0.00 | π 1.0x (baseline) |
| @pas7/nestjs-strict-json (v0.5.0) | 6.30 | 21.03 | β 0.85x (18% slower) |
| jsonc-parser + JSON.parse | 51.18 | 112.88 | |
| @pas7/nestjs-strict-json (v0.4.x baseline) | 80.71 | 146.61 | β 0.07x (24x slower) |
# Using npm
npm install @pas7/nestjs-strict-json
# Using bun (optional, faster)
bun add @pas7/nestjs-strict-jsonimport { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { registerStrictJson } from "@pas7/nestjs-strict-json";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
registerStrictJson(app);
await app.listen(3000);
}
bootstrap();Important: disable default body parser so duplicate keys are not lost before strict parsing.
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { registerStrictJson } from "@pas7/nestjs-strict-json";
async function bootstrap() {
const app = await NestFactory.create(AppModule, { bodyParser: false });
registerStrictJson(app);
await app.listen(3000);
}
bootstrap();import express from "express";
import { createStrictJsonExpressMiddleware } from "@pas7/nestjs-strict-json";
const app = express();
app.use(
createStrictJsonExpressMiddleware({
maxBodySizeBytes: 1024 * 1024,
enableStreaming: true,
streamingThreshold: 100 * 1024,
}),
);
app.post("/api", (req, res) => {
res.json({ received: req.body });
});
app.listen(3000);import Fastify from "fastify";
import { registerStrictJsonFastify } from "@pas7/nestjs-strict-json";
const server = Fastify();
registerStrictJsonFastify(server, { maxBodySizeBytes: 1024 * 1024 });
server.post("/api", async (request) => request.body);
server.listen({ port: 3000 });registerStrictJson(app, options?)StrictJsonModule.forRoot(options?)
createStrictJsonExpressMiddleware(options?)registerStrictJsonFastify(instance, options?)
parseStrictJson(raw, options?)parseStrictJsonAsync(raw, options?)clearParseCache()getParseCacheSize()
shutdownCacheManager()- graceful shutdown of cleanup interval (call on app shutdown)resetCacheManager()- full cache reset for testingisCleanupIntervalRunning()- check if cleanup interval is activegetCachedValidator(key)- get or create cached validatorclearValidatorCache()- clear validator cachegetValidatorCacheSize()- get current cache size
type StrictJsonOptions = {
maxBodySizeBytes?: number;
enablePrototypePollutionProtection?: boolean;
dangerousKeys?: string[];
whitelist?: string[];
blacklist?: string[];
maxDepth?: number;
ignoreCase?: boolean;
enableStreaming?: boolean;
streamingThreshold?: number;
chunkSize?: number;
lazyMode?: boolean;
lazyModeThreshold?: number;
lazyModeDepthLimit?: number;
lazyModeSkipPrototype?: boolean;
lazyModeSkipWhitelist?: boolean;
lazyModeSkipBlacklist?: boolean;
enableCache?: boolean;
cacheSize?: number;
cacheTTL?: number;
enableFastPath?: boolean;
onDuplicateKey?: (error: unknown) => void | Promise<void>;
onInvalidJson?: (error: unknown) => void | Promise<void>;
onBodyTooLarge?: (error: unknown) => void | Promise<void>;
onPrototypePollution?: (error: unknown) => void | Promise<void>;
onError?: (error: unknown) => void | Promise<void>;
};STRICT_JSON_DUPLICATE_KEYSTRICT_JSON_INVALID_JSONSTRICT_JSON_BODY_TOO_LARGESTRICT_JSON_PROTOTYPE_POLLUTIONSTRICT_JSON_DEPTH_LIMIT
registerStrictJson(app, {
maxBodySizeBytes: 1024 * 1024,
enablePrototypePollutionProtection: true,
maxDepth: 20,
enableCache: true,
enableFastPath: true,
});- Node.js 20+
- NestJS 10+
- Express 4+
- Fastify 4+
- User Guide - current file
- Optimization Guide - detailed optimization guide
- Performance Report - detailed performance report
- π Article: Understanding JSON Security Vulnerabilities - deep dive into the problems this package solves
For support, please:
- Open an issue
- Contact us via our website
PAS7 - Software development company
Apache-2.0