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-to-json-mapper

v2.1.0

Published

Remap JSON to JSON from a declarative list of source/target paths — with type casting, lookup tables, arrays, and zero runtime dependencies.

Readme

build npm license: MIT

json-to-json-mapper

Remap one JSON shape into another from a small, declarative list of { source, target } rules — with optional type casting, lookup tables, array handling, and per-mapping error reporting.

  • Zero runtime dependencies.
  • Pure & statelessmap() never mutates its inputs and keeps no state between calls, so it is safe to reuse and call concurrently.
  • Safe by default — target paths that would pollute the prototype chain (__proto__, constructor, prototype) are rejected.
  • Typed — ships with TypeScript declarations.
  • ESM and CommonJS — dual builds selected automatically by import / require.

Install

pnpm add json-to-json-mapper
# or: npm install json-to-json-mapper

Quick start

import { map } from "json-to-json-mapper";
// or: const { map } = require("json-to-json-mapper");

const input = {
  request: { order: { id: "1" } },
};

const { result, skipped, errors } = map(input, [
  { source: "request.order.id", target: "app.ordering.number", cast: "number" },
]);

// result  => { app: { ordering: { number: 1 } } }
// skipped => []      (input leaves that no mapping consumed)
// errors  => []      (per-mapping problems, never thrown)

map(input, mappings, options?) returns { result, skipped, errors } and never throws for a per-mapping problem — failures are collected in errors so a partial result is always available. (It only throws if mappings itself is not an array.)

Mapping options

| Field | Type | Description | | ----------- | -------------------------------------- | --------------------------------------------------------------------------- | | source | string (required) | Dot-path into the input, e.g. request.order.id. Arrays are traversed. | | target | string (required) | Dot-path into the output. Use $ to denote an array level. | | cast | "string" \| "number" \| "boolean" | Coerce the value's type. The String/Number/Boolean constructors work too. | | lookup | Record<string \| number, unknown> | Substitute the value via a table or a TypeScript enum. | | transform | (value: unknown) => unknown | Arbitrary transform, applied last. | | default | unknown | Value to use when the source resolves to nothing. | | first | boolean | Keep only the first matched value (for a scalar target fed by an array). |

Order of application per value: lookup → cast → transform.

Casting

map({ id: "42" }, [{ source: "id", target: "id", cast: "number" }]);
// { id: 42 }

Booleans understand common string forms: "true"/"1"/"yes"/"on"true, "false"/"0"/"no"/"off"/""false. An impossible cast (e.g. "abc" to a number) is reported in errors, not thrown.

Lookup tables and enums

map({ code: 2 }, [
  { source: "code", target: "label", lookup: { 1: "A", 2: "B" } },
]);
// { label: "B" }

A TypeScript enum is just an object at runtime (including its reverse numeric-to-name entries), so it can be passed directly as a lookup.

Arrays and the $ syntax

An array in the middle of a source path is traversed element by element. In the target, a $ segment marks where an array should be built:

map({ request: { order: [{ id: "1" }, { id: "2" }] } }, [
  { source: "request.order.id", target: "app.ordering.$.id", cast: "number" },
]);
// { app: { ordering: [{ id: 1 }, { id: 2 }] } }

Source array positions are preserved, which keeps multiple field-mappings aligned to the same element. An element that contributes no fields becomes an empty slot (serialized as null) — pass { compactArrays: true } to get dense arrays instead. To fold an array source into a single scalar target, use first: true.

A numeric segment picks one array element deliberately:

map({ order: [{ id: "a" }, { id: "b" }] }, [
  { source: "order.1.id", target: "picked" },
]);
// { picked: "b" }

skipped and errors

  • skipped lists input leaf paths (in dot notation) that no mapping consumed — handy for spotting fields you forgot to map.
  • errors is an array of { source, target, message } describing every mapping that could not be fully applied (bad cast, lookup miss, unsafe target key, malformed mapping).

Map-level options

map(input, mappings, {
  into: existingObject, // merge into this object instead of a fresh one
  strict: true,         // missing sources (without a default) become errors
  compactArrays: true,  // remove holes from arrays in the result
});

Migrating from v1

v2 is a rewrite. The old API was stateful, crashed on the documented call signature, and silently mismatched its own README. Key changes:

  • Signature: map(input, mappings) (or map(input, mappings, { into })). The old required 4th initial argument is gone; pass { into } if you need it.
  • Casting uses the cast field with "string" | "number" | "boolean" (constructors still accepted). The old, undocumented behavior of the format key is removed — use lookup for enums and cast for types.
  • skipped is now string[] (was { source }[]).
  • enum option is replaced by the more general lookup.
  • Statelessness & security: results no longer leak between calls, and unsafe target keys are rejected.

Development

pnpm install
pnpm run build       # compile to dist/
pnpm test            # type-check tests, then run them with node:test
pnpm run typecheck   # type-check everything without emitting

Tests use Node's built-in test runner (node:test), so there are no test dependencies. Requires Node.js >= 18.

License

MIT © Rodrigo Nunes