npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

json-codemod

v2.0.0

Published

A utility to patch the JSON string and preserve the original formatting, including comments and whitespace.

Readme

json-codemod

Badge LICENSE Node npm version

Modify JSON strings with a fluent chainable API while preserving formatting, comments, and whitespace.

✨ Features

  • 🎨 Format Preservation - Maintains comments, whitespace, and original formatting
  • 🔗 Chainable API - Fluent interface for readable modifications
  • Sequential Operations - Apply multiple changes in order
  • 🚀 Fast & Lightweight - Zero dependencies, minimal footprint
  • 📦 Dual module support - Works with both ESM and CommonJS
  • 💪 TypeScript Support - Full type definitions included
  • 🎯 Flexible Path Syntax - Supports both dot notation and JSON Pointer

📦 Installation

npm install json-codemod

Or using other package managers:

yarn add json-codemod
# or
pnpm add json-codemod

🚀 Quick Start

import jsonmod from "json-codemod";

const source = '{"name": "Alice", "age": 30, "items": [1, 2, 3]}';

const result = jsonmod(source)
  .replace("name", '"Bob"')
  .replace("age", "31")
  .delete("items[1]")
  .insert("items", 2, "4")
  .apply();

// Result: {"name": "Bob", "age": 31, "items": [1, 4, 3]}

With Value Helpers

Use formatValue for automatic type handling:

import jsonmod, { formatValue } from "json-codemod";

const source = '{"name": "Alice", "age": 30, "active": false}';

const result = jsonmod(source)
  .replace("name", formatValue("Bob"))    // Strings quoted automatically
  .replace("age", formatValue(31))        // Numbers handled correctly
  .replace("active", formatValue(true))   // Booleans too
  .apply();

// Result: {"name": "Bob", "age": 31, "active": true}

📖 API Reference

jsonmod(sourceText)

Creates a chainable instance for JSON modifications.

Parameters:

  • sourceText (string): JSON string to modify

Returns: JsonMod instance

Example:

const mod = jsonmod('{"name": "Alice"}');

.replace(path, value)

Replace a value at the specified path.

Parameters:

  • path (string | string[]): JSON path
  • value (string): New value as JSON string

Returns: this (chainable)

Examples:

// Simple replacement
jsonmod(source).replace("name", '"Bob"').apply();

// Nested path
jsonmod(source).replace("user.profile.age", "31").apply();

// Array element
jsonmod(source).replace("items[1]", "99").apply();

// Using formatValue
jsonmod(source).replace("name", formatValue("Bob")).apply();

.delete(path) / .remove(path)

Delete a property or array element.

Parameters:

  • path (string | string[]): JSON path

Returns: this (chainable)

Examples:

// Delete property
jsonmod(source).delete("age").apply();

// Delete array element
jsonmod(source).delete("items[0]").apply();

// Delete nested property
jsonmod(source).delete("user.email").apply();

// Multiple deletions (remove is alias)
jsonmod(source)
  .delete("a")
  .remove("b")
  .apply();

.insert(path, keyOrPosition, value)

Insert into objects or arrays.

Parameters:

  • path (string | string[]): Path to container
  • keyOrPosition (string | number): Property name (object) or index (array)
  • value (string): Value as JSON string

Returns: this (chainable)

Examples:

// Insert into object
jsonmod(source)
  .insert("", "email", '"[email protected]"')
  .apply();

// Insert into array at position
jsonmod(source)
  .insert("items", 0, '"first"')
  .apply();

// Append to array
jsonmod(source)
  .insert("items", 3, '"last"')
  .apply();

// Using formatValue
jsonmod(source)
  .insert("user", "age", formatValue(30))
  .apply();

.apply()

Execute all queued operations and return modified JSON.

Returns: Modified JSON string

Example:

const result = jsonmod(source)
  .replace("a", "1")
  .delete("b")
  .insert("", "c", "3")
  .apply();  // Execute and return result

formatValue(value)

Convert JavaScript values to JSON strings automatically.

Parameters:

  • value (any): JavaScript value

Returns: JSON string representation

Examples:

import { formatValue } from "json-codemod";

formatValue(42)          // "42"
formatValue("hello")     // '"hello"'
formatValue(true)        // "true"
formatValue(null)        // "null"
formatValue({a: 1})      // '{"a":1}'
formatValue([1, 2, 3])   // '[1,2,3]'

🎯 Examples

Configuration File Updates

import jsonmod, { formatValue } from "json-codemod";
import { readFileSync, writeFileSync } from "fs";

const config = readFileSync("tsconfig.json", "utf-8");

const updated = jsonmod(config)
  .replace("compilerOptions.target", formatValue("ES2022"))
  .replace("compilerOptions.strict", formatValue(true))
  .delete("compilerOptions.experimentalDecorators")
  .insert("compilerOptions", "moduleResolution", formatValue("bundler"))
  .apply();

writeFileSync("tsconfig.json", updated);

Preserving Comments and Formatting

const source = `{
  // User configuration
  "name": "Alice",
  "age": 30, /* years */
  "active": true
}`;

const result = jsonmod(source)
  .replace("age", "31")
  .replace("active", "false")
  .apply();

// Comments and formatting preserved!

Complex Nested Operations

const data = '{"user": {"name": "Alice", "settings": {"theme": "dark"}}}';

const result = jsonmod(data)
  .replace("user.name", formatValue("Bob"))
  .replace("user.settings.theme", formatValue("light"))
  .insert("user.settings", "language", formatValue("en"))
  .apply();

Array Manipulations

const source = '{"items": [1, 2, 3, 4, 5]}';

const result = jsonmod(source)
  .delete("items[1]")      // Remove second item
  .delete("items[2]")      // Remove what is now third item
  .insert("items", 0, "0") // Insert at beginning
  .apply();

// Result: {"items": [0, 1, 4, 5]}

Conditional Operations

let mod = jsonmod(config);

if (isDevelopment) {
  mod = mod.replace("debug", "true");
}

if (needsUpdate) {
  mod = mod.replace("version", formatValue("2.0.0"));
}

const result = mod.apply();

📚 Path Syntax

Dot Notation

jsonmod(source).replace("user.profile.name", '"Bob"').apply();

Bracket Notation for Arrays

jsonmod(source).replace("items[0]", "1").apply();
jsonmod(source).delete("items[2]").apply();

JSON Pointer

jsonmod(source).replace("/user/profile/name", '"Bob"').apply();

Special Characters

For keys with special characters, use JSON Pointer:

// Key with slash: "a/b"
jsonmod(source).replace("/a~1b", "value").apply();

// Key with tilde: "a~b"
jsonmod(source).replace("/a~0b", "value").apply();

💻 TypeScript Support

Full TypeScript support with type definitions:

import jsonmod, { JsonMod, formatValue } from "json-codemod";

const source = '{"name": "Alice", "age": 30}';

const instance: JsonMod = jsonmod(source);

const result: string = instance
  .replace("name", formatValue("Bob"))
  .delete("age")
  .apply();

🔧 How It Works

  1. Parse: Creates a Concrete Syntax Tree (CST) preserving all formatting
  2. Queue: Operations are queued, not executed immediately
  3. Execute: .apply() runs operations sequentially, re-parsing after each
  4. Return: Returns the modified JSON string with formatting preserved

❓ FAQ

Why use formatValue?

Without formatValue:

.replace("name", '"Bob"')    // Must remember quotes
.replace("age", "30")         // No quotes for numbers
.replace("active", "true")    // No quotes for booleans

With formatValue:

.replace("name", formatValue("Bob"))    // Automatic
.replace("age", formatValue(30))        // Automatic
.replace("active", formatValue(true))   // Automatic

How are comments preserved?

The library parses JSON into a Concrete Syntax Tree that includes comments and whitespace as tokens. Modifications only change value tokens, leaving everything else intact.

What about performance?

Operations are applied sequentially with re-parsing between each. This ensures correctness but means:

  • Fast for small to medium JSON files
  • For large files with many operations, consider batching similar changes

Can I reuse a JsonMod instance?

No, call .apply() returns a string and operations are cleared. Create a new instance for new modifications:

const result1 = jsonmod(source).replace("a", "1").apply();
const result2 = jsonmod(result1).replace("b", "2").apply();

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

Anti 996 License

🔗 Links

🌟 Star History

Star History Chart