JSON File Database for Node.js
node-json-db is a lightweight, file-based database for Node.js, storing data directly in a JSON file. It is currently at stable version 2.6.0 and maintains an active release cadence, with several minor and patch releases occurring monthly or bi-monthly in the past year. Its primary differentiator is the use of a "DataPath" system, akin to XMLPath, for navigating and accessing nested data structures within the JSON file. All operations are asynchronous, leveraging `async/await`. It supports configurable database names, auto-save on push, human-readable file formats, custom separators, and since v2.6.0, serialization of complex JavaScript types like `Set`, `Map`, `Date`, `RegExp`, and `BigInt` via an `ISerializer` contract. This makes it suitable for simple, local data persistence where a full-fledged database system is overkill.
Common errors
-
Error: DataPath '/your/non/existent/path' doesn't exist. Failed at /your.
cause You are attempting to retrieve data using `db.getData()` from a path that does not exist in the database.fixCheck if the path exists before calling `getData()`, or wrap the call in a `try-catch` block. For convenience, use `db.getObjectDefault('/path', defaultValue)` (available since v2.2.0) to get a value or a fallback. -
TypeError: JsonDB is not a constructor
cause Incorrect `import` or `require()` syntax, often trying to use CommonJS `require()` with this ESM-first package, or incorrect named import for `JsonDB`.fixEnsure your project is configured for ESM (`"type": "module"` in `package.json` or `.mjs` file extension) and use `import { JsonDB, Config } from 'node-json-db';`. -
SyntaxError: await is only valid in async functions and the top level bodies of modules
cause You are calling `JsonDB` methods (which are `async`) outside of an `async` function or a top-level `await` context.fixEnsure all calls to `db.push()`, `db.getData()`, etc., are made from within an `async` function. For example, wrap your main logic in `async function main() { ... }` and call `main().catch(console.error);`. -
TypeError: Class constructor Config cannot be invoked without 'new'
cause You are attempting to instantiate the `Config` class without using the `new` keyword, which is required for JavaScript classes.fixAlways initialize `Config` with `new Config(...)` when passing it to `JsonDB`, for example: `new JsonDB(new Config('filename', true, false, '/'))`.
Warnings
- breaking All `JsonDB` methods became asynchronous in v2.0.0. Direct calls without `await` will result in unresolved promises or unexpected behavior. Your code context must support `async/await`.
- breaking Database initialization now *requires* the `Config` object in v2.0.0. Passing arguments directly to the `JsonDB` constructor is no longer supported.
- gotcha The `push` method will overwrite existing data at a given `DataPath` by default. Merging requires explicitly setting the third argument to `false`.
- gotcha When using `push` with the merge flag set to `false`, merging only applies to objects and arrays. Attempting to merge a primitive value (string, number, boolean) into an existing primitive will still result in an override.
- gotcha Attempting to retrieve data using `getData` from a `DataPath` that does not exist will throw a `DataError`.
- gotcha In versions `v2.4.0` and `v2.4.1`, several class exports (e.g., `DataError`, `DatabaseError`, adapters) were inadvertently broken, leading to import failures or `TypeError`s.
Install
-
npm install node-json-db -
yarn add node-json-db -
pnpm add node-json-db
Imports
- JsonDB
import JsonDB from 'node-json-db'; const JsonDB = require('node-json-db');import { JsonDB } from 'node-json-db' - Config
const Config = require('node-json-db').Config;import { Config } from 'node-json-db' - DataError
import { DataError } from 'node-json-db/lib/Errors'import { DataError, DatabaseError } from 'node-json-db'
Quickstart
import { JsonDB, Config, DataError } from "node-json-db";
import * as fs from 'fs'; // For cleanup
async function runExample() {
const dbFileName = "myQuickstartDatabase";
const dbFilePath = `${dbFileName}.json`;
// Clean up previous run if exists
if (fs.existsSync(dbFilePath)) {
fs.unlinkSync(dbFilePath);
}
// Initialize JsonDB with a Config object
// Arguments: filename, autoSave (true), humanReadable (false), separator ('/'), syncWrites (false)
const db = new JsonDB(new Config(dbFileName, true, false, "/", false));
console.log("Database initialized.");
// Push simple string data to a path
await db.push("/user/name", "Alice Wonderland");
console.log("Pushed /user/name: Alice Wonderland");
// Push an object, creating hierarchy if needed
await db.push("/settings", { theme: "dark", notifications: true });
console.log("Pushed /settings: { theme: 'dark', notifications: true }");
// Merge new data into an existing object path (third argument 'false' for merge)
await db.push(
"/settings",
{ notifications: false, language: "en-US" },
false
);
console.log("Merged into /settings: { notifications: false, language: 'en-US' }");
console.log("Current /settings:", await db.getData("/settings"));
// Get data from a specific path
const userName = await db.getData("/user/name");
console.log("Retrieved /user/name:", userName);
// Attempt to get data from a non-existent path and catch the expected error
try {
await db.getData("/nonexistent/path");
} catch (error) {
if (error instanceof DataError) {
console.error(`Caught expected error for non-existent path: ${error.message}`);
} else {
console.error("Caught unexpected error:", error);
}
}
// Get the entire database content
const fullData = await db.getData("/");
console.log("Full database content:\n", JSON.stringify(fullData, null, 2));
console.log("\nQuickstart example finished.");
}
runExample().catch(console.error);