{"id":17937704,"url":"https://github.com/kleber-swf/deepmerge-json","last_synced_at":"2025-03-24T08:33:38.485Z","repository":{"id":48116576,"uuid":"194690267","full_name":"kleber-swf/deepmerge-json","owner":"kleber-swf","description":"A library to deep merge json files with array operations","archived":false,"fork":false,"pushed_at":"2024-06-17T02:15:18.000Z","size":332,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-19T03:37:17.939Z","etag":null,"topics":["clone","copy","deepmerge","extend","javascript","json","merge","recursive","typescript"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kleber-swf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-01T14:36:45.000Z","updated_at":"2025-02-26T21:58:36.000Z","dependencies_parsed_at":"2024-11-17T05:36:19.885Z","dependency_job_id":"840d6c1a-8a6c-4375-9865-d5722f9bd194","html_url":"https://github.com/kleber-swf/deepmerge-json","commit_stats":{"total_commits":86,"total_committers":3,"mean_commits":"28.666666666666668","dds":0.2674418604651163,"last_synced_commit":"3b129fa6ea58d046a14ed5819407deff616f1720"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleber-swf%2Fdeepmerge-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleber-swf%2Fdeepmerge-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleber-swf%2Fdeepmerge-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kleber-swf%2Fdeepmerge-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kleber-swf","download_url":"https://codeload.github.com/kleber-swf/deepmerge-json/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245000779,"owners_count":20545114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clone","copy","deepmerge","extend","javascript","json","merge","recursive","typescript"],"created_at":"2024-10-28T23:06:55.503Z","updated_at":"2025-03-24T08:33:38.194Z","avatar_url":"https://github.com/kleber-swf.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deepmerge Json\n\n[![Build Status](https://travis-ci.org/kleber-swf/deepmerge-json.svg?branch=master)](https://travis-ci.org/kleber-swf/deepmerge-json)\n![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/kleber-swf/deepmerge-json.svg)\n![npm](https://img.shields.io/npm/v/deepmerge-json)\n![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/kleber-swf/deepmerge-json)\n\n# What\n\nA simple library to deep merge json files with array operations. Hugely inspired by the awesome [deepmerge](https://github.com/TehShrike/deepmerge) project.\n\n\u003e Note that you can use to merge javascript objects, but the main reason this library was created was to merge json files with optional special operations for array merging.\n\n# Why\n\nSometimes you need a deeply copied objects. Sometimes you need to alter these objects to make them more extensible and generic, specially when you are using [convention over configuration](https://en.wikipedia.org/wiki/Convention_over_configuration) or [convention over code](https://en.wikipedia.org/wiki/Convention_over_Code) patterns.\n\nThe objective of this library is to help you with these situations being really simple, performatic and small (~1.5kb).\n\n# How\n\n```js\nlet left = {\n  keep: 'keep',\n  simple: 10,\n  obj: { a: { multi: { level: 'property' } }, is: 'ok' },\n  merge: [0, 1, 2, 3],\n  append: [0, 1, 2],\n  prepend: [0, 1, 2]\n};\n\nlet right = {\n  simple: 20,\n  obj: { a: { multi: { level: 'and' }, deep: 'property' } },\n  merge: [10, 20],\n  append: { $append: [3, 4, 5] },\n  prepend: { $prepend: [-2, -1] }\n};\n\nlet result = merge(left, right);\nconsole.log(result);\n\n// Result\n{\n  keep: 'keep',\n  simple: 20,\n  obj: { a: { multi: { level: 'and' }, deep: 'property' }, is: 'ok' },\n  merge: [10, 20, 2, 3],\n  append: [0, 1, 2, 3, 4, 5],\n  prepend: [-2, -1, 0, 1, 2]\n}\n```\n\n**Explanation:** it deeply merges `right` object into `left` without altering them and their properties. Everything is cloned. Arrays elements are merged based on `right` parameters (operators) passed as objects.\n\n# Installation\n\n## With NPM\n\n```sh\nnpm install deepmerge-json\n```\n\nAfter that you can import it:\n\n```js\nimport merge from 'deepmerge-json';\n```\n\nor\n\n```js\nconst merge = require('deepmerge-json');\n```\n\nThere is even a Typescript `d.ts` definition file to support auto complete.\n\n## With a CDN\n\nJust add this line to your HTML file:\n\n```html\n\u003cscript src=\"https://unpkg.com/deepmerge-json@latest/dist/deepmerge-json.min.js\u003e\u003c/script\u003e\n```\n\n# Usage\n\nThe main reason this library was created was to mimic and extend some array merging functions from mongodb when merging two sets of properties json files.\n\n## Simple Merge\n\nIt is possible to merge recursively all types of properties.\n\n```js\nconst left = {\n  boolValue: false,\n  numberValue: 100,\n  stringValue: 'target',\n  objectValue: {\n    foo: 0,\n    bar: 'bar',\n    baz: {\n      baz1: 1,\n      baz2: 2\n    }\n  }\n};\n\nconst right = {\n  boolValue: true,\n  numberValue: 222,\n  stringValue: 'source',\n  objectValue: {\n    foo: 'foo',\n    baz: {\n      baz3: 3\n    }\n  }\n};\n\nconst res = merge(left, right);\n\n// result\n{\n  boolValue: true,\n  numberValue: 222,\n  stringValue: 'source',\n  objectValue: {\n    foo: 'foo',\n    bar: 'bar',\n    baz: {\n      baz1: 1,\n      baz2: 2,\n      baz3: 3\n    }\n  }\n}\n```\n\n## Clone\n\nYou can clone an object omitting the second parameter. This will execute the `merge` function with an empty second parameter, which results in a deep clone of the first one.\n\nNotice that if you pass anything other than `undefined` to the second parameter (even `null`), it will be actively used in the merge process.\n\nYou can also use the `merge.clone()` method which is an alias to the `merge` method with a single parameter. It's also more semantically meaningful.\n\n## Array Merge\n\nMerging arrays are special because sometimes you want to append elements, sometimes prepend and sometimes you want to merge them.\n\nMongodb handles this nicely (IMHO). It has a [`$push` property](https://docs.mongodb.com/manual/reference/operator/update/push/) (among others) that let you append elements to an array when updating a document.\n\nInspired on that, this library has some merging methods (here called **operations**) to help you merge or improve the arrays from the original object. Just keep in mind that no matter the depth of the array, you just need to have the same path to the objects you want to merge.\n\n### Merging Elements\n\nThis is the default behavior. It merges the arrays elements one by one. It will add elements to the end if there more on the right than on the left element.\n\n```js\nconst left = {\n  foo: [1, 2, 3],\n  bar: []\n};\n\nconst right = {\n  foo: [10, 20],\n  bar: [10, 20, 30]\n};\n\nconst result = merge(left, right)\n\n// Result\n{\n  foo: [10, 20, 3],\n  bar: [10, 20, 30]\n}\n```\n\n### $push / $append\n\nYou can use the `$push` or `$append` operation to add elements to the end of the \"left\" array.\n\n```js\nconst left = [0, 1, 2];\nconst right = { $push: [3, 4, 5] };\nconst result = merge(left, right);\n\n// Result\n[0, 1, 2, 3, 4, 5];\n```\n\n### $prepend\n\nSimilarly, you can use `$prepend` operation to add elements to the beginning of the \"left\" array.\n\n```js\nconst left = [0, 1, 2];\nconst right = { $prepend: [-2, -1] };\nconst result = merge(left, right);\n\n// Result\n[-2, -1, 0, 1, 2];\n```\n\n### $set\n\nUse `$set` when you want to completely replace \"left\" array by the \"right\" one.\n\n```js\nconst left = [0, 1, 2, 3, 4, 5, 6];\nconst right = { $set: [10, 20] };\nconst result = merge(left, right);\n\n// Result\n[10, 20];\n```\n\n### $replace\n\nUse `$replace` to replace or add indexed elements by their indexes. Indexes can be numbers or strings and cannot be less than 0 or `NaN` values.\n\n#### With valid indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $replace: { 0: 100, 2: 300, 4: 400 } };\nconst result = merge(left, right);\n\n// Result (note that the element with index 3 was never given)\n[100, 20, 300, , 400];\n```\n\n#### With invalid indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $replace: { null: 0, foo: 0, true: 0, '-1': 0 } };\nconst result = merge(left, right);\n\n// throws an Error\n```\n\n#### With objects\n\n`[1.4.0]` It completely replaces the indicated left element with the corresponding right element.\n\n\u003e **Note for users of version `\u003c 1.4.0`**: if you want the old operation functionality, replace `$replace` for [`$merge`](#merge).\n\n```js\nconst left = [{ a: 1, b: 1 }, { c: 1 }];\nconst right = { $merge: [{ a: 2 }] };\nconst result = merge(left, right);\n\n// Result\n[{ a: 2 }, { c: 1 }];\n```\n\n### $merge\n\nUse `$merge` to merge or add indexed elements by their indexes. Indexes can be numbers or strings and cannot be less than 0 or `NaN` values. It's similar to [`$replace`](#replace) but instead of replacing the values when found, it merges them with the new values.\n\n#### With valid indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $merge: { 0: 100, 2: 300, 4: 400 } };\nconst result = merge(left, right);\n\n// Result (note that the element with index 3 was never given)\n[100, 20, 300, , 400];\n```\n\n#### With invalid indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $merge: { null: 0, foo: 0, true: 0, '-1': 0 } };\nconst result = merge(left, right);\n\n// throws an Error\n```\n\n#### With objects\n\n```js\nconst left = [{ a: 1, b: 1 }, { c: 1 }];\nconst right = { $merge: [{ a: 2 }] };\nconst result = merge(left, right);\n\n// Result\n[{ a: 2, b: 1 }, { c: 1 }];\n```\n\n### $insert\n\nUse `$insert` to insert indexed elements at their indexes. Indexes can be numbers or strings and cannot `NaN` values. Notice that elements change places as you insert them. Negative numbers insert them to the end of the array. See [Array.splice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice).\n\n#### With positive indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $insert: { 0: 100, 2: 200, 10: 400 } };\nconst result = merge(left, right);\n\n// Result (notice that the elements moved and the 400 was added to the last index)\n[100, 10, 200, 20, 30, 400];\n```\n\n#### With negative indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $insert: { '-1': 100, '-2': 200, '-10': 0 } };\nconst result = merge(left, right);\n\n// Result\n[0, 10, 20, 200, 100, 30];\n```\n\n#### With invalid indexes:\n\n```js\nconst left = [10, 20, 30];\nconst right = { $insert: { null: 100, foo: 300, true: 400 } };\nconst result = merge(left, right);\n\n// throws an Error\n```\n\n### Skipping Elements\n\nIf you skip some elements in the \"right\" array, the respective \"left\" elements will be kept in the result. This is not very useful for json merging since it's ot possible to create a sparse array _per se_, but it's a nice consequence of the `merge` method.\n\n```js\nconst left = [1, 20, 3, 40, 5, 60];\nconst right = [10, , 30, , 50];\nconst result = merge(left, right);\n\n// Result\n[10, 20, 30, 40, 50, 60];\n```\n\n### Multiple Operations\n\nStarting from version `1.3.0` it's possible to use multiple operations at once. They are executed in place and in order.\n\n```js\nconst left = [2, 3, 4];\nconst right: {\n  $prepend: [0, 1],\n  $append: [5, 6],\n  $replace: { 0: 100 };\n}\nconst result = merge(left, right);\n\n// Result\n[100, 1, 2, 3, 4, 5, 6]\n```\n\n```js\nconst left = [2, 3, 4];\nconst right: {\n  $replace: { 0: 100 };\n  $prepend: [0, 1],\n  $append: [5, 6],\n}\nconst result = merge(left, right);\n\n// Result\n[0, 1, 100, 3, 4, 5, 6]\n```\n\n## Merging Multiple Objects\n\nYou can also merge multiple objects with the help of the utility method `merge.multi()`. It respects the order of the parameters and the operations just like expected if you call `merge` multiple times passing the last result as the first parameter to the next call.\n\n```js\nconst obj1 = { a: 0, b: [true, { c: 'ok' }] };\nconst obj2 = { a: 10, d: false };\nconst obj3 = { a: 20, b: { $push: [42] } };\n\nconst result = merge.multi(obj1, obj2, obj3);\n\n// Result\n{ a: 20, b: [true, { c: 'ok' }, 42], d: false }\n```\n\n## Options\n\nFor now, no options yet :chipmunk:.\n\n# Contributing\n\nIf you are nice enough you can submit bugs and features to the issue board and make this lib great and useful for you and the community.\n\nBut if you are really nice you can submit a PR and make this lib awesome!\n\n# Rough Performance Test\n\nJust a fun performance test with a 1 million runs. I'm not a performance expert so they might not be very precise.\n\nTesting machine:\n\n-   CPU: Intel Core i5-9300H @ 2.4GHz x8\n-   Memory: 32GB\n-   SO: Ubuntu 20.04.4 LTS\n\n| Measures            | Node 17.7.2 | Chrome 100.0.4896.75 | Firefox 99.0 \u003csup\u003e2\u003c/sup\u003e :thinking: |\n| ------------------- | ----------- | -------------------- | ------------------------------------ |\n| Max. Value          | 279,763.93  | 295,386.07           | 852,514.92                           |\n| Min. Value          | 277,344.35  | 287,802.91           | 827,814.57                           |\n| Average\u003csup\u003e1\u003c/sup\u003e | 279,574.05  | 293,929.66           | 840,884.13                           |\n\n-   Operations per second\n-   \u003csup\u003e1\u003c/sup\u003e The average is calculated removing the maximum and the minimum values\n-   \u003csup\u003e2\u003c/sup\u003e For some reason Firefox returned a really good but suspicious performance\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkleber-swf%2Fdeepmerge-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkleber-swf%2Fdeepmerge-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkleber-swf%2Fdeepmerge-json/lists"}