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

json2ai

v0.0.5

Published

Convert JSON to a compact, AI-friendly text format

Readme

json2ai

Convert JSON into a compact, AI-friendly text format. Reduces token usage and formats nested data for readable consumption by LLM-based tools. Optionally wrap output in a Markdown fenced code block.

Install

npm install json2ai

Usage

import json2ai from "json2ai";

const out = json2ai({
  user: { id: 1, name: "ryuyx", active: true },
  tags: ["ts", "node"],
  users: [
    { id: 1, name: "a" },
    { id: 2, name: "b" },
  ],
});

Produces:

user:
 id: 1
 name: ryuyx
 active: true
tags:
 ts, node
users:
 | index | id | name |
 | --- | --- | --- |
 | 0 | 1 | a |
 | 1 | 2 | b |

Arrays of homogeneous objects are rendered as a Markdown table (field names emitted once, one row per item) to avoid repeating the same keys and wasting tokens — friendlier for LLMs than raw JSON. Nested sub-objects and sub-arrays are fused into their cell as compact inline notation ({u:3 r:{id:x}}) instead of nesting deeper.

Token savings

By dropping JSON's syntax overhead (quotes, braces, colons, commas) and emitting repeated structural keys only once, json2ai shrinks the payload a well-known model needs to read. Measured in characters (a reasonable token proxy), four representative inputs — arrays of objects with repeated keys and nested records — shrink by about one-third in md format and by roughly half in the more compact tsv format:

Token savings with json2ai

Per-sample reduction: users ×50 −34% md / −54% tsv, users ×500 −34% / −52%, orders ×30 −35% / −48%, orders ×200 −36% / −47%. Savings grow with redundancy: the more repeated keys and nested structure a payload has, the more a reader can drop. Regenerate the chart with python3 scripts/plot_tokens.py.

API

json2ai(value, options?) => string

Options

| Option | Type | Default | Description | | ---------------- | ---------- | -------- | ----------------------------------------------------------------- | | indent | string | " " | Indentation string for nested objects. | | format | "md"|"tsv"| "md" | Table format for object arrays. "md" (friendly, +tokens) or "tsv" (compact, −tokens). | | maxArrayItems | number | — | Truncate large arrays, summarizing skipped items with a count. | | wrapInCodeBlock| boolean | false | Wrap output in a fenced Markdown code block. | | codeBlockLang | string | "text" | Fence language for wrapInCodeBlock. | | omit | string[] | [] | Key names to drop (e.g. secrets). Matches key names at any depth. | | rename | Record<string, string \| { alias?: string; unit?: string; type?: "date" }> | {} | Remap keys by dotted path to an alias, a unit suffix, and/or a timestamp conversion. Array indices are skipped, so a path like "users.name" matches every row. |

Example: renaming

const out = json2ai(
  { products: [{ name: "a", price: 100, qty: 3 }] },
  {
    rename: {
      "products.name": "title",
      "products.price": { unit: "USD" },
      "products.qty": { alias: "count", unit: "pcs" },
    },
  }
);

Produces:

products:
 | index | title | price | count |
 | --- | --- | --- | --- |
 | 0 | a | 100 USD | 3 pcs |

A path maps either to a string alias ("products.name": "title") or to an object with an optional alias, an optional unit, and an optional type. { unit: "USD" } renames nothing but appends the unit; { alias: "count", unit: "pcs" } does both. Units apply to scalar leaf values only.

type: "date" converts a numeric leaf to an ISO 8601 UTC timestamp, auto-detecting seconds vs milliseconds by magnitude (>= 1e12 is milliseconds):

const out = json2ai(
  { user: { name: "ryuyx", created_at: 1756814400 } },
  { rename: { "user.created_at": { alias: "created", type: "date" } } }
);
user:
 name: ryuyx
 created: 2025-09-02T12:00:00.000Z

Non-numeric values pass through unchanged. When type and unit are both set on a date leaf, type takes precedence.

License

MIT