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

@naman22khater/json-mapper

v1.0.2

Published

A powerful JSON mapping and transformation engine

Readme

@naman22khater/json-mapper

A powerful JSON mapping and transformation engine for converting data from one schema to another. Perfect for ETL pipelines, API integrations, and data migration tasks.

npm version License: MIT

Features

  • 🔄 Schema-based Mapping - Define source and target schemas with field-level mappings
  • 📦 Array Support - Handle nested arrays with wildcard (*) path notation
  • 🔧 Built-in Transformations - Convert types, format strings, parse dates, and more
  • Custom Transformations - Define your own transformation functions
  • Validation - Validate source data against schemas
  • 📊 Batch Processing - Transform multiple objects in a single call
  • 🎯 TypeScript Support - Full type definitions included

Installation

npm install @naman22khater/json-mapper
yarn add @naman22khater/json-mapper
pnpm add @naman22khater/json-mapper

Quick Start

import { JsonMapperEngine, createMapper, MappingConfig } from '@naman22khater/json-mapper';

// Define your mapping configuration
const config: MappingConfig = {
  version: '1.0',
  source: {
    name: 'UserAPI',
    fields: [
      { id: 'src-1', name: 'user_name', type: 'String' },
      { id: 'src-2', name: 'user_email', type: 'String' },
      { id: 'src-3', name: 'is_active', type: 'Boolean' },
    ],
  },
  target: {
    name: 'CRM',
    fields: [
      { id: 'tgt-1', name: 'fullName', type: 'String' },
      { id: 'tgt-2', name: 'emailAddress', type: 'String' },
      { id: 'tgt-3', name: 'status', type: 'String' },
    ],
  },
  mappings: [
    { id: 'map-1', sourceFieldId: 'src-1', targetFieldId: 'tgt-1' },
    { id: 'map-2', sourceFieldId: 'src-2', targetFieldId: 'tgt-2' },
    { 
      id: 'map-3', 
      sourceFieldId: 'src-3', 
      targetFieldId: 'tgt-3',
      transformation: 'toString' 
    },
  ],
};

// Create the mapper
const mapper = createMapper(config);

// Transform data
const result = mapper.transform({
  user_name: 'John Doe',
  user_email: '[email protected]',
  is_active: true,
});

console.log(result);
// {
//   success: true,
//   data: {
//     fullName: 'John Doe',
//     emailAddress: '[email protected]',
//     status: 'true'
//   }
// }

Working with Nested Objects

const config: MappingConfig = {
  version: '1.0',
  source: {
    name: 'Source',
    fields: [
      {
        id: 'src-addr',
        name: 'address',
        type: 'Object',
        children: [
          { id: 'src-street', name: 'street', type: 'String' },
          { id: 'src-city', name: 'city', type: 'String' },
        ],
      },
    ],
  },
  target: {
    name: 'Target',
    fields: [
      {
        id: 'tgt-location',
        name: 'location',
        type: 'Object',
        children: [
          { id: 'tgt-addr', name: 'streetAddress', type: 'String' },
          { id: 'tgt-city', name: 'cityName', type: 'String' },
        ],
      },
    ],
  },
  mappings: [
    { id: 'map-1', sourceFieldId: 'src-street', targetFieldId: 'tgt-addr' },
    { id: 'map-2', sourceFieldId: 'src-city', targetFieldId: 'tgt-city' },
  ],
};

const mapper = createMapper(config);

const result = mapper.transform({
  address: {
    street: '123 Main St',
    city: 'New York',
  },
});

// Result:
// {
//   location: {
//     streetAddress: '123 Main St',
//     cityName: 'New York'
//   }
// }

Working with Arrays

The engine supports array traversal using the * wildcard notation. When you define a field inside an Array type, the path automatically includes .* to indicate array element access.

const config: MappingConfig = {
  version: '1.0',
  source: {
    name: 'OrdersAPI',
    fields: [
      {
        id: 'src-orders',
        name: 'orders',
        type: 'Array',
        children: [
          { id: 'src-product', name: 'product_name', type: 'String' },
          { id: 'src-qty', name: 'quantity', type: 'Number' },
        ],
      },
    ],
  },
  target: {
    name: 'Inventory',
    fields: [
      {
        id: 'tgt-items',
        name: 'items',
        type: 'Array',
        children: [
          { id: 'tgt-name', name: 'name', type: 'String' },
          { id: 'tgt-count', name: 'count', type: 'Number' },
        ],
      },
    ],
  },
  mappings: [
    // Maps orders.*.product_name → items.*.name
    { id: 'map-1', sourceFieldId: 'src-product', targetFieldId: 'tgt-name' },
    // Maps orders.*.quantity → items.*.count
    { id: 'map-2', sourceFieldId: 'src-qty', targetFieldId: 'tgt-count' },
  ],
};

const mapper = createMapper(config);

const result = mapper.transform({
  orders: [
    { product_name: 'Widget', quantity: 5 },
    { product_name: 'Gadget', quantity: 3 },
  ],
});

// Result:
// {
//   items: [
//     { name: 'Widget', count: 5 },
//     { name: 'Gadget', count: 3 }
//   ]
// }

Transformations

The engine supports several built-in transformations:

| Transformation | Description | Example | |---------------|-------------|---------| | direct | Copy value as-is (default) | "hello""hello" | | toString | Convert to string | 123"123" | | toNumber | Convert to number | "42"42 | | toBoolean | Convert to boolean | "true"true | | toUpperCase | Convert string to uppercase | "hello""HELLO" | | toLowerCase | Convert string to lowercase | "HELLO""hello" | | trim | Remove whitespace from string ends | " hello ""hello" | | dateFormat | Format date values | "2024-01-01""2024-01-01T00:00:00.000Z" | | custom | Apply custom transformation | User-defined |

Using Transformations

const mappings = [
  {
    id: 'map-1',
    sourceFieldId: 'src-name',
    targetFieldId: 'tgt-name',
    transformation: 'toUpperCase',
  },
  {
    id: 'map-2',
    sourceFieldId: 'src-price',
    targetFieldId: 'tgt-price',
    transformation: 'toNumber',
    transformationOptions: {
      defaultValue: 0, // Used if conversion fails
    },
  },
  {
    id: 'map-3',
    sourceFieldId: 'src-date',
    targetFieldId: 'tgt-date',
    transformation: 'dateFormat',
    transformationOptions: {
      dateFormat: 'ISO',
    },
  },
];

Custom Transformations

const mappings = [
  {
    id: 'map-1',
    sourceFieldId: 'src-price',
    targetFieldId: 'tgt-price',
    transformation: 'custom',
    transformationOptions: {
      customFunction: 'value * 1.1', // Add 10% markup
    },
  },
];

API Reference

JsonMapperEngine

The main class for performing transformations.

Constructor

new JsonMapperEngine(config: MappingConfig)

Methods

transform(sourceData: Record<string, unknown>): MappingResult

Transform a single source object to the target format.

const result = mapper.transform({ name: 'John' });
// Returns: { success: boolean, data?: object, errors?: MappingError[] }
transformBatch(sourceDataArray: Record<string, unknown>[]): MappingResult[]

Transform an array of source objects.

const results = mapper.transformBatch([
  { name: 'John' },
  { name: 'Jane' },
]);
validateSource(sourceData: Record<string, unknown>): { valid: boolean, errors: string[] }

Validate source data against the source schema.

const validation = mapper.validateSource({ name: 'John' });
if (!validation.valid) {
  console.log(validation.errors);
}
generateSampleOutput(): Record<string, unknown>

Generate an empty target structure based on the target schema.

const sample = mapper.generateSampleOutput();
// Returns target structure with default values
getConfig(): MappingConfig

Get the current mapping configuration.

setConfig(config: MappingConfig): void

Update the mapping configuration.

createMapper(config: MappingConfig): JsonMapperEngine

Factory function to create a new mapper instance.

const mapper = createMapper(config);

Types

Field

interface Field {
  id: string;
  name: string;
  type: FieldType; // 'String' | 'Number' | 'Boolean' | 'Object' | 'Array'
  children?: Field[];
  expanded?: boolean;
}

Mapping

interface Mapping {
  id: string;
  sourceFieldId: string;
  targetFieldId: string;
  transformation?: TransformationType;
  transformationOptions?: TransformationOptions;
}

MappingConfig

interface MappingConfig {
  version: string;
  source: SourceConfig;
  target: TargetConfig;
  mappings: Mapping[];
}

MappingResult

interface MappingResult {
  success: boolean;
  data?: Record<string, unknown>;
  errors?: MappingError[];
}

MappingError

interface MappingError {
  field: string;
  message: string;
  sourceValue?: unknown;
}

File Format (.jmap)

The JSON Mapper uses .jmap files for storing mapping configurations. These files are JSON-formatted and contain the complete mapping configuration:

{
  "version": "1.0",
  "exportedAt": "2026-01-04T12:00:00.000Z",
  "source": {
    "name": "SourceSystem",
    "fields": [...]
  },
  "target": {
    "name": "TargetSystem", 
    "fields": [...]
  },
  "mappings": [...]
}

Error Handling

The engine provides detailed error information when transformations fail:

const result = mapper.transform(data);

if (!result.success) {
  result.errors?.forEach(error => {
    console.log(`Field: ${error.field}`);
    console.log(`Message: ${error.message}`);
    console.log(`Source Value: ${error.sourceValue}`);
  });
}

License

MIT © Naman Khater

Contributing

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