{"id":35165291,"url":"https://github.com/axetroy/json-codemod","last_synced_at":"2026-04-29T07:32:25.763Z","repository":{"id":328930904,"uuid":"1117310491","full_name":"axetroy/json-codemod","owner":"axetroy","description":"Modify JSON strings with a fluent chainable API while preserving formatting, comments, and whitespace.","archived":false,"fork":false,"pushed_at":"2026-01-04T03:37:15.000Z","size":188,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-15T23:52:28.002Z","etag":null,"topics":["json","json-parse","json-replace","jsoncst"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/json-codemod","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axetroy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"axetroy","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://github.com/axetroy/buy-me-a-cup-of-tea"}},"created_at":"2025-12-16T06:12:43.000Z","updated_at":"2026-01-04T03:37:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/axetroy/json-codemod","commit_stats":null,"previous_names":["axetroy/jsoncst"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/axetroy/json-codemod","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axetroy%2Fjson-codemod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axetroy%2Fjson-codemod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axetroy%2Fjson-codemod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axetroy%2Fjson-codemod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axetroy","download_url":"https://codeload.github.com/axetroy/json-codemod/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axetroy%2Fjson-codemod/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32416145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T06:29:02.080Z","status":"ssl_error","status_checked_at":"2026-04-29T06:29:00.631Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["json","json-parse","json-replace","jsoncst"],"created_at":"2025-12-28T19:28:13.495Z","updated_at":"2026-04-29T07:32:25.757Z","avatar_url":"https://github.com/axetroy.png","language":"JavaScript","funding_links":["https://github.com/sponsors/axetroy","https://github.com/axetroy/buy-me-a-cup-of-tea"],"categories":[],"sub_categories":[],"readme":"# json-codemod\n\n[![Badge](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg?style=flat-square)](https://996.icu/#/en_US)\n[![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg?style=flat-square)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n![Node](https://img.shields.io/badge/node-%3E=14-blue.svg?style=flat-square)\n[![npm version](https://badge.fury.io/js/json-codemod.svg)](https://badge.fury.io/js/json-codemod)\n\nModify JSON strings with a fluent chainable API while preserving formatting, comments, and whitespace.\n\n## ✨ Features\n\n-   🎨 **Format Preservation** - Maintains comments, whitespace, and original formatting\n-   🔗 **Chainable API** - Fluent interface for readable modifications\n-   ⚡ **Sequential Operations** - Apply multiple changes in order\n-   🚀 **Fast \u0026 Lightweight** - Zero dependencies, minimal footprint\n-   📦 **Dual module support** - Works with both ESM and CommonJS\n-   💪 **TypeScript Support** - Full type definitions included\n-   🎯 **Flexible Path Syntax** - Supports both dot notation and JSON Pointer\n\n## 📦 Installation\n\n```bash\nnpm install json-codemod\n```\n\nOr using other package managers:\n\n```bash\nyarn add json-codemod\n# or\npnpm add json-codemod\n```\n\n## 🚀 Quick Start\n\n```js\nimport jsonmod from \"json-codemod\";\n\nconst source = '{\"name\": \"Alice\", \"age\": 30, \"items\": [1, 2, 3]}';\n\nconst result = jsonmod(source)\n  .replace(\"name\", '\"Bob\"')\n  .replace(\"age\", \"31\")\n  .delete(\"items[1]\")\n  .insert(\"items\", 2, \"4\")\n  .apply();\n\n// Result: {\"name\": \"Bob\", \"age\": 31, \"items\": [1, 4, 3]}\n```\n\n### With Value Helpers\n\nUse `formatValue` for automatic type handling:\n\n```js\nimport jsonmod, { formatValue } from \"json-codemod\";\n\nconst source = '{\"name\": \"Alice\", \"age\": 30, \"active\": false}';\n\nconst result = jsonmod(source)\n  .replace(\"name\", formatValue(\"Bob\"))    // Strings quoted automatically\n  .replace(\"age\", formatValue(31))        // Numbers handled correctly\n  .replace(\"active\", formatValue(true))   // Booleans too\n  .apply();\n\n// Result: {\"name\": \"Bob\", \"age\": 31, \"active\": true}\n```\n\n## 📖 API Reference\n\n### `jsonmod(sourceText)`\n\nCreates a chainable instance for JSON modifications.\n\n**Parameters:**\n- `sourceText` (string): JSON string to modify\n\n**Returns:** `JsonMod` instance\n\n**Example:**\n```js\nconst mod = jsonmod('{\"name\": \"Alice\"}');\n```\n\n### `.replace(path, value)`\n\nReplace a value at the specified path.\n\n**Parameters:**\n- `path` (string | string[]): JSON path\n- `value` (string): New value as JSON string\n\n**Returns:** `this` (chainable)\n\n**Examples:**\n```js\n// Simple replacement\njsonmod(source).replace(\"name\", '\"Bob\"').apply();\n\n// Nested path\njsonmod(source).replace(\"user.profile.age\", \"31\").apply();\n\n// Array element\njsonmod(source).replace(\"items[1]\", \"99\").apply();\n\n// Using formatValue\njsonmod(source).replace(\"name\", formatValue(\"Bob\")).apply();\n```\n\n### `.delete(path)` / `.remove(path)`\n\nDelete a property or array element.\n\n**Parameters:**\n- `path` (string | string[]): JSON path\n\n**Returns:** `this` (chainable)\n\n**Examples:**\n```js\n// Delete property\njsonmod(source).delete(\"age\").apply();\n\n// Delete array element\njsonmod(source).delete(\"items[0]\").apply();\n\n// Delete nested property\njsonmod(source).delete(\"user.email\").apply();\n\n// Multiple deletions (remove is alias)\njsonmod(source)\n  .delete(\"a\")\n  .remove(\"b\")\n  .apply();\n```\n\n### `.insert(path, keyOrPosition, value)`\n\nInsert into objects or arrays.\n\n**Parameters:**\n- `path` (string | string[]): Path to container\n- `keyOrPosition` (string | number): Property name (object) or index (array)\n- `value` (string): Value as JSON string\n\n**Returns:** `this` (chainable)\n\n**Examples:**\n```js\n// Insert into object\njsonmod(source)\n  .insert(\"\", \"email\", '\"test@example.com\"')\n  .apply();\n\n// Insert into array at position\njsonmod(source)\n  .insert(\"items\", 0, '\"first\"')\n  .apply();\n\n// Append to array\njsonmod(source)\n  .insert(\"items\", 3, '\"last\"')\n  .apply();\n\n// Using formatValue\njsonmod(source)\n  .insert(\"user\", \"age\", formatValue(30))\n  .apply();\n```\n\n### `.apply()`\n\nExecute all queued operations and return modified JSON.\n\n**Returns:** Modified JSON string\n\n**Example:**\n```js\nconst result = jsonmod(source)\n  .replace(\"a\", \"1\")\n  .delete(\"b\")\n  .insert(\"\", \"c\", \"3\")\n  .apply();  // Execute and return result\n```\n\n### `formatValue(value)`\n\nConvert JavaScript values to JSON strings automatically.\n\n**Parameters:**\n- `value` (any): JavaScript value\n\n**Returns:** JSON string representation\n\n**Examples:**\n```js\nimport { formatValue } from \"json-codemod\";\n\nformatValue(42)          // \"42\"\nformatValue(\"hello\")     // '\"hello\"'\nformatValue(true)        // \"true\"\nformatValue(null)        // \"null\"\nformatValue({a: 1})      // '{\"a\":1}'\nformatValue([1, 2, 3])   // '[1,2,3]'\n```\n\n## 🎯 Examples\n\n### Configuration File Updates\n\n```js\nimport jsonmod, { formatValue } from \"json-codemod\";\nimport { readFileSync, writeFileSync } from \"fs\";\n\nconst config = readFileSync(\"tsconfig.json\", \"utf-8\");\n\nconst updated = jsonmod(config)\n  .replace(\"compilerOptions.target\", formatValue(\"ES2022\"))\n  .replace(\"compilerOptions.strict\", formatValue(true))\n  .delete(\"compilerOptions.experimentalDecorators\")\n  .insert(\"compilerOptions\", \"moduleResolution\", formatValue(\"bundler\"))\n  .apply();\n\nwriteFileSync(\"tsconfig.json\", updated);\n```\n\n### Preserving Comments and Formatting\n\n```js\nconst source = `{\n  // User configuration\n  \"name\": \"Alice\",\n  \"age\": 30, /* years */\n  \"active\": true\n}`;\n\nconst result = jsonmod(source)\n  .replace(\"age\", \"31\")\n  .replace(\"active\", \"false\")\n  .apply();\n\n// Comments and formatting preserved!\n```\n\n### Complex Nested Operations\n\n```js\nconst data = '{\"user\": {\"name\": \"Alice\", \"settings\": {\"theme\": \"dark\"}}}';\n\nconst result = jsonmod(data)\n  .replace(\"user.name\", formatValue(\"Bob\"))\n  .replace(\"user.settings.theme\", formatValue(\"light\"))\n  .insert(\"user.settings\", \"language\", formatValue(\"en\"))\n  .apply();\n```\n\n### Array Manipulations\n\n```js\nconst source = '{\"items\": [1, 2, 3, 4, 5]}';\n\nconst result = jsonmod(source)\n  .delete(\"items[1]\")      // Remove second item\n  .delete(\"items[2]\")      // Remove what is now third item\n  .insert(\"items\", 0, \"0\") // Insert at beginning\n  .apply();\n\n// Result: {\"items\": [0, 1, 4, 5]}\n```\n\n### Conditional Operations\n\n```js\nlet mod = jsonmod(config);\n\nif (isDevelopment) {\n  mod = mod.replace(\"debug\", \"true\");\n}\n\nif (needsUpdate) {\n  mod = mod.replace(\"version\", formatValue(\"2.0.0\"));\n}\n\nconst result = mod.apply();\n```\n\n## 📚 Path Syntax\n\n### Dot Notation\n\n```js\njsonmod(source).replace(\"user.profile.name\", '\"Bob\"').apply();\n```\n\n### Bracket Notation for Arrays\n\n```js\njsonmod(source).replace(\"items[0]\", \"1\").apply();\njsonmod(source).delete(\"items[2]\").apply();\n```\n\n### JSON Pointer\n\n```js\njsonmod(source).replace(\"/user/profile/name\", '\"Bob\"').apply();\n```\n\n### Special Characters\n\nFor keys with special characters, use JSON Pointer:\n\n```js\n// Key with slash: \"a/b\"\njsonmod(source).replace(\"/a~1b\", \"value\").apply();\n\n// Key with tilde: \"a~b\"\njsonmod(source).replace(\"/a~0b\", \"value\").apply();\n```\n\n## 💻 TypeScript Support\n\nFull TypeScript support with type definitions:\n\n```typescript\nimport jsonmod, { JsonMod, formatValue } from \"json-codemod\";\n\nconst source = '{\"name\": \"Alice\", \"age\": 30}';\n\nconst instance: JsonMod = jsonmod(source);\n\nconst result: string = instance\n  .replace(\"name\", formatValue(\"Bob\"))\n  .delete(\"age\")\n  .apply();\n```\n\n## 🔧 How It Works\n\n1. **Parse:** Creates a Concrete Syntax Tree (CST) preserving all formatting\n2. **Queue:** Operations are queued, not executed immediately\n3. **Execute:** `.apply()` runs operations sequentially, re-parsing after each\n4. **Return:** Returns the modified JSON string with formatting preserved\n\n## ❓ FAQ\n\n### Why use formatValue?\n\n**Without formatValue:**\n```js\n.replace(\"name\", '\"Bob\"')    // Must remember quotes\n.replace(\"age\", \"30\")         // No quotes for numbers\n.replace(\"active\", \"true\")    // No quotes for booleans\n```\n\n**With formatValue:**\n```js\n.replace(\"name\", formatValue(\"Bob\"))    // Automatic\n.replace(\"age\", formatValue(30))        // Automatic\n.replace(\"active\", formatValue(true))   // Automatic\n```\n\n### How are comments preserved?\n\nThe library parses JSON into a Concrete Syntax Tree that includes comments and whitespace as tokens. Modifications only change value tokens, leaving everything else intact.\n\n### What about performance?\n\nOperations are applied sequentially with re-parsing between each. This ensures correctness but means:\n- Fast for small to medium JSON files\n- For large files with many operations, consider batching similar changes\n\n### Can I reuse a JsonMod instance?\n\nNo, call `.apply()` returns a string and operations are cleared. Create a new instance for new modifications:\n\n```js\nconst result1 = jsonmod(source).replace(\"a\", \"1\").apply();\nconst result2 = jsonmod(result1).replace(\"b\", \"2\").apply();\n```\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## 📄 License\n\n[Anti 996 License](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n\n## 🔗 Links\n\n-   [GitHub](https://github.com/axetroy/json-codemod)\n-   [npm](https://www.npmjs.com/package/json-codemod)\n\n## 🌟 Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=axetroy/json-codemod\u0026type=Date)](https://star-history.com/#axetroy/json-codemod\u0026Date)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxetroy%2Fjson-codemod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxetroy%2Fjson-codemod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxetroy%2Fjson-codemod/lists"}