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-traversal

v1.19.1

Published

Json Transformer Utility. Many times you want to interact with 3rd party services or clients, this utility acts as an adaptor and help you mantain code clean by maintaining only the json mappings

Readme

JSON Transformer

A JSON-to-JSON transformation engine where the source JSON contains the data and the transformation JSON describes the output.

The important idea is simple:

SOURCE JSON + TRANSFORMATION JSON
                │
                ▼
        transformed JSON

The transformation is not a second copy of the source. It is an output recipe: it decides which output keys exist, where their values come from, and whether a nested result is an object or an array.

This repository is maintained as a practical JSON transformation engine. Its current implementation is especially useful for JSON produced from XML/Tally-style structures, where keys such as ALLINVENTORYENTRIES.LIST contain literal dots and where a collection may arrive sometimes as one object and sometimes as an array.

Installation

npm install json-traversal

Basic usage

import transformer from "json-traversal";

const source = {
    name: "Keshav",
    city: "Yamuna Nagar"
};

const transformation = {
    mapping: {
        item: {
            customerName: "name",
            customerCity: "city"
        }
    }
};

const result = transformer.transform(source, transformation);

console.log(result);

Output:

{
  "customerName": "Keshav",
  "customerCity": "Yamuna Nagar"
}

The mental model

Think of the two JSON documents as two sides of a mapping:

LEFT / SOURCE                         RIGHT / OUTPUT RECIPE
─────────────────                    ─────────────────────
name: Keshav             ────────▶   customerName: "name"
city: Yamuna Nagar       ────────▶   customerCity: "city"

The keys on the transformation side become keys in the output. The string values on the transformation side are instructions for finding values in the source.

This means the output can be:

  • smaller than the source;
  • larger in shape than the source;
  • renamed;
  • nested differently;
  • converted from object to array;
  • converted from array to one selected object;
  • composed from nested arrays;
  • populated with constants;
  • type-converted or processed by supported actions.

The source does not have to look like the output.

The core rule

An object mapping describes an output object:

{
    mapping: {
        item: {
            name: "NAME",
            city: "CITY"
        }
    }
}

An array mapping describes an output array:

{
    items: [
        {
            list: "ITEMS",
            item: {
                name: "NAME"
            }
        }
    ]
}

The same pattern can be placed inside another pattern. That is what makes array inside array and deeper structures possible.

A smaller output from a bigger source

Source:

{
  "id": 1001,
  "name": "Keshav",
  "city": "Yamuna Nagar",
  "phone": "9999999999",
  "internalCode": "SECRET",
  "unusedField": "remove me"
}

Transformation:

const transformation = {
    mapping: {
        item: {
            id: "id",
            name: "name",
            city: "city"
        }
    }
};

Output:

{
  "id": 1001,
  "name": "Keshav",
  "city": "Yamuna Nagar"
}

The transformation defines the output. Unmentioned source fields are not automatically copied.

A larger output shape from a smaller source

A transformation can also create a larger shape than the source by nesting existing values into new output objects or arrays.

Source:

{
  "name": "Keshav",
  "city": "Yamuna Nagar"
}

Transformation:

const transformation = {
    mapping: {
        item: {
            customer: {
                item: {
                    name: "name",
                    location: {
                        item: {
                            city: "city"
                        }
                    }
                }
            }
        }
    }
};

Output:

{
  "customer": {
    "name": "Keshav",
    "location": {
      "city": "Yamuna Nagar"
    }
  }
}

The output shape is described by the transformation, not inherited from the source.

Arrays

Source:

{
  "items": [
    { "name": "ROPE", "amount": 260 },
    { "name": "CABLE", "amount": 540 }
  ]
}

Transformation:

const transformation = {
    mapping: {
        item: {
            products: [
                {
                    list: "items",
                    item: {
                        productName: "name",
                        amount: "amount"
                    }
                }
            ]
        }
    }
};

Output:

{
  "products": [
    { "productName": "ROPE", "amount": 260 },
    { "productName": "CABLE", "amount": 540 }
  ]
}

Array inside array

An array mapping can contain another array mapping.

Source:

{
  "orders": [
    {
      "number": 1001,
      "items": [
        { "name": "ROPE", "batches": ["A", "B"] },
        { "name": "CABLE", "batches": ["C"] }
      ]
    },
    {
      "number": 1002,
      "items": [
        { "name": "MESH", "batches": ["D", "E"] }
      ]
    }
  ]
}

Transformation:

const transformation = {
    mapping: {
        item: {
            orders: [
                {
                    list: "orders",
                    item: {
                        number: "number",
                        items: [
                            {
                                list: "items",
                                item: {
                                    name: "name",
                                    batches: [
                                        {
                                            list: "batches",
                                            item: {
                                                value: ""
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
};

For a complete catalogue of nested-array patterns, see docs/arrays.md.

Tally / XML-derived JSON

A major practical case is JSON whose property names themselves contain dots:

{
  "ALLINVENTORYENTRIES.LIST": [
    {
      "STOCKITEMNAME": "ROPE",
      "BATCHALLOCATIONS.LIST": {
        "BATCHID": {
          "#text": 3543
        }
      }
    }
  ]
}

Here the dot in ALLINVENTORYENTRIES.LIST is part of the property name. It is not the same thing as the navigation path:

customer.address.city

The current resolver therefore supports both:

customer.address.city

and literal dotted keys such as:

ALLINVENTORYENTRIES.LIST
BATCHALLOCATIONS.LIST
LEDGERENTRIES.LIST
ALLLEDGERENTRIES.LIST

It resolves the longest matching property name before continuing through the path.

This behavior is documented in docs/path-resolution.md.

Object-to-array normalization

Tally-style data can represent a collection as one object in one record and an array in another record. The transformation can deliberately expose the result as an array:

batch: [
    {
        list: "BATCHALLOCATIONS.LIST",
        item: {
            batchId: "BATCHID.#text",
            batchName: "BATCHNAME",
            amount: "AMOUNT"
        }
    }
]

If the source collection is an array, each entry is transformed. If it is not a non-empty array, the current array traversal returns an empty array.

This makes the output contract explicit: batch is an array in the transformation model.

Nested Tally example

A voucher can be expressed as:

const transformation = {
    mapping: {
        item: {
            vouchers: [
                {
                    list: "items",
                    item: {
                        voucherNumber: "VOUCHERNUMBER",
                        items: [
                            {
                                list: "ALLINVENTORYENTRIES.LIST",
                                item: {
                                    stockItem: "STOCKITEMNAME",
                                    batch: [
                                        {
                                            list: "BATCHALLOCATIONS.LIST",
                                            item: {
                                                batchId: "BATCHID.#text",
                                                batchName: "BATCHNAME",
                                                amount: "AMOUNT"
                                            }
                                        }
                                    ],
                                    accounting: [
                                        {
                                            list: "ACCOUNTINGALLOCATIONS.LIST",
                                            item: {
                                                ledger: "LEDGERNAME",
                                                amount: "AMOUNT"
                                            }
                                        }
                                    ]
                                }
                            }
                        ],
                        ledger: [
                            {
                                list: "LEDGERENTRIES.LIST",
                                item: {
                                    name: "LEDGERNAME.#text",
                                    amount: "AMOUNT.#text"
                                }
                            }
                        ],
                        allLedger: [
                            {
                                list: "ALLLEDGERENTRIES.LIST",
                                item: {
                                    name: "LEDGERNAME",
                                    amount: "AMOUNT"
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
};

The important part is not Tally itself. The important part is that the same transformation mechanism composes repeatedly:

voucher array
    └── inventory array
          ├── batch array
          └── accounting array
    ├── ledger array
    └── allLedger array

Supported mapping families

| Mapping | Purpose | |---|---| | item | Describe an output object | | list | Read a source collection and transform every item | | objectify | Wrap a source value into an array mapping | | flat | Select one indexed element from a source array and map it as an object | | collect | Build an array from several mapping instructions | | $value | Hard-code a value | | (TYPE) | Apply supported type conversion | | {ACTION} | Apply a supported action | | ^path | Resolve a path against the root source |

See docs/mapping-language.md for the full syntax currently implemented by V5.

Architecture

The implementation has two important walks:

                  transform(source, transformation)
                              │
                              ▼
                       mapping traversal
                              │
             ┌────────────────┼────────────────┐
             ▼                ▼                ▼
          object            array            value
             │                │                │
             │                │                └── resolveValue()
             │                │                         │
             │                │                         ▼
             │                │                    resolvePath()
             │                │
             │                └── resolve source collection
             │
             └── recursively traverse child mapping

                              ▼
                         output JSON

The source lookup logic is intentionally separate from mapping traversal:

  • traverse.js understands the transformation structure.
  • resolve.js understands source paths.
  • value.js resolves one mapping instruction and delegates special behavior.
  • actions.js contains conversions and actions.
  • constants.js contains the mapping syntax identifiers.

See docs/architecture.md.

Tests and stories

The repository contains focused tests and progressive implementation folders. The V5 story tests are especially useful because they demonstrate:

  • recursive object output;
  • source arrays mapped to output arrays;
  • ordinary dotted paths;
  • literal dotted property names.

The Tally voucher story is under test/v7/ and uses the real-world structure needed by the project.

Run tests with:

npm test

Documentation map

Project identity

The repository package is currently named json-traversal in package.json. The implementation is a JSON transformer: the transformation mapping drives traversal and output construction.

The project should be understood from behavior and architecture rather than from the historical version names alone.

License

See the license information retained by the upstream project and the repository's package metadata before redistributing a derivative package.

cloned from

https://github.com/Sudhirmiglani/node-json-transformer