{"id":10746,"library":"diff-json","title":"JSON Object Diffing and Patching","description":"diff-json is a JavaScript library (version 2.0.0, last updated in 2017) designed to generate structural differences between JavaScript objects, and subsequently apply or revert those changes. Inspired by `eugeneware/changeset`, it offers `diff`, `applyChanges`, and `revertChanges` functionalities. A key differentiator is its ability to handle array diffing by specifying a primary key for embedded objects, ensuring accurate comparison beyond simple positional changes. However, due to its age and lack of maintenance since 2017, it does not support modern JavaScript features like ES Modules or TypeScript and has an uncertain future regarding bug fixes or security updates. Alternative modern libraries like `json-diff-ts` offer similar functionality with current ecosystem support.","status":"abandoned","version":"2.0.0","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/viruschidai/diff-json","tags":["javascript","JSON","diff","patch","revert","apply changes","revert changes"],"install":[{"cmd":"npm install diff-json","lang":"bash","label":"npm"},{"cmd":"yarn add diff-json","lang":"bash","label":"yarn"},{"cmd":"pnpm add diff-json","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This library is CommonJS-only. There is no official ES module export. Attempting to use `import` syntax will fail without a transpiler or bundler.","wrong":"import changesets from 'diff-json';","symbol":"changesets","correct":"const changesets = require('diff-json');"},{"note":"The library primarily exports an object containing its functions. While some environments might allow destructuring from `require`, the intended and common usage demonstrated in examples is to import the entire `changesets` object. No native named ESM exports exist.","wrong":"import { diff } from 'diff-json';","symbol":"diff","correct":"const { diff } = require('diff-json'); // Although technically possible to destructure, the common pattern is to import the entire object."},{"note":"Functions like `applyChanges` are methods of the `changesets` object exported by the CommonJS module. Direct named imports are not supported.","wrong":"import { applyChanges } from 'diff-json';","symbol":"applyChanges","correct":"const changesets = require('diff-json'); changesets.applyChanges(oldObj, diffs);"}],"quickstart":{"code":"const changesets = require('diff-json');\n\nconst oldObj = {\n  name: 'joe',\n  age: 55,\n  coins: [2, 5],\n  children: [\n    {name: 'kid1', age: 1},\n    {name: 'kid2', age: 2}\n  ]\n};\n\nconst newObj = {\n  name: 'smith',\n  coins: [2, 5, 1],\n  children: [\n    {name: 'kid3', age: 3},\n    {name: 'kid1', age: 0},\n    {name: 'kid2', age: 2}\n  ]\n};\n\n// Generate a diff, specifying 'name' as the primary key for children array elements\nconst diffs = changesets.diff(oldObj, newObj, {children: 'name'});\n\nconsole.log('Generated Diffs:', JSON.stringify(diffs, null, 2));\n/*\nExample Output (truncated):\n[\n  { \"type\": \"update\", \"key\": \"name\", \"value\": \"smith\", \"oldValue\": \"joe\" },\n  { \"type\": \"update\", \"key\": \"coins\", \"embededKey\": \"$index\", \"changes\": [ { \"type\": \"add\", \"key\": \"2\", \"value\": 1 } ] },\n  { \"type\": \"update\", \"key\": \"children\", \"embededKey\": \"name\", \"changes\": [ { \"type\": \"update\", \"key\": \"kid1\", \"changes\": [ { \"type\": \"update\", \"key\": \"age\", \"value\": 0, \"oldValue\": 1 } ] }, { \"type\": \"add\", \"key\": \"kid3\", \"value\": { \"name\": \"kid3\", \"age\": 3 } } ] },\n  { \"type\": \"remove\", \"key\": \"age\", \"value\": 55 }\n]\n*/\n\n// Apply changes to a base object\nconst targetObj = JSON.parse(JSON.stringify(oldObj)); // Deep clone to avoid mutating oldObj\nchangesets.applyChanges(targetObj, diffs);\n\nconsole.log('\\nObject after applying changes:', JSON.stringify(targetObj, null, 2));\n\n// Revert changes on a modified object to get back to the original state\nconst revertableObj = JSON.parse(JSON.stringify(newObj)); // Start with newObj to revert to oldObj state\nconst revertedDiffs = changesets.revertChanges(diffs); // Revert the diffs themselves\nchangesets.applyChanges(revertableObj, revertedDiffs);\n\nconsole.log('\\nObject after reverting changes:', JSON.stringify(revertableObj, null, 2));","lang":"javascript","description":"This quickstart demonstrates how to generate a diff between two JSON objects, apply those changes to an object, and then revert the changes to restore a previous state. It highlights the use of the `embededKey` option for intelligent array diffing."},"warnings":[{"fix":"Evaluate actively maintained alternatives like `json-diff-ts` (which supports ESM and TypeScript, and offers key-based array identification similar to `diff-json`), `jsondiffpatch`, or `@incutio/diff-json` for modern applications.","message":"The `diff-json` package has been abandoned since its last update in September 2017. This means it lacks support for modern JavaScript features like ES Modules, may contain unpatched bugs or security vulnerabilities, and will not receive new features or maintenance. Users should consider migrating to actively maintained alternatives.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure your project uses CommonJS (`require()`) or uses a bundler (like Webpack, Rollup) to transpile CommonJS modules for ESM consumption. For new projects, consider libraries with native ESM support.","message":"This library is CommonJS-only and does not provide native ES module support. Using `import` statements directly will result in errors in native ESM environments (e.g., Node.js with `\"type\": \"module\"` in `package.json`) without transpilation.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Consider using `@ts-ignore` for imports, or create custom declaration files (`.d.ts`) for the functions you use. For a fully type-safe solution, migrate to a TypeScript-first library.","message":"The library does not provide TypeScript type definitions. Developers using TypeScript will have to either write their own declarations or use it without type safety.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Always provide the `embededKey` option (e.g., `{ children: 'name' }`) in the `changesets.diff()` call when dealing with arrays of objects that should be matched by a unique identifier.","message":"When diffing arrays containing objects, `diff-json` requires an `embededKey` option to correctly identify and compare elements. If this key is not provided, arrays are diffed by index, which can lead to incorrect or non-intuitive diffs if elements are reordered or new elements are inserted.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change the file to CommonJS (`.js` without `\"type\": \"module\"` or explicitly `.cjs` extension) or use a bundler to convert the `diff-json` CommonJS module to an ES module format during compilation. Alternatively, migrate to an ES module-compatible diffing library.","cause":"Attempting to use `require()` in a JavaScript file that is treated as an ES module (e.g., due to `\"type\": \"module\"` in `package.json` or a `.mjs` extension).","error":"ReferenceError: require is not defined in ES module scope"},{"fix":"Ensure you are importing the entire `changesets` object using `const changesets = require('diff-json');` and then calling its methods as `changesets.diff(...)`, `changesets.applyChanges(...)`, etc.","cause":"This error typically occurs if the library was imported incorrectly, or if you attempted to destructure `diff` directly from `require('diff-json')` in an environment where it's not supported, expecting named exports that don't exist.","error":"TypeError: changesets.diff is not a function"},{"fix":"Provide a unique `embededKey` for array elements in the third argument of `changesets.diff(oldObj, newObj, { arrayKey: 'uniquePropertyName' })` to enable intelligent, key-based array item matching.","cause":"When comparing arrays of objects, `diff-json` defaults to index-based comparison if no `embededKey` is provided. If objects within the array are reordered or partially updated without a key, the diff might incorrectly show elements as removed and added rather than updated.","error":"Unexpected array diff results (e.g., entire objects marked as 'add'/'remove' instead of 'update' for reordered items)."}],"ecosystem":"npm"}