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 🙏

© 2024 – Pkg Stats / Ryan Hefner

map-json

v0.1.7

Published

Maps objects into a given JSON structure

Downloads

76

Readme

map-json

license issues Coverage Status

Library to map objects into a given JSON structure

Installation

Install via npm:

$ npm install map-json

Documentation

Usage

MapJson.map(sourceObject, mappingObject, functionSource?, preProcessFunction?)

Basic Mapping Object Syntax

The mapping object defines the structure of the created JSON object. All objects that contain a _source tag will be replaced with its respective data from the source object.

Example mapping object:

{
  name: 'John', // This will be kept as is
  data: {
    id: 123, // This will be kept as is
    username: {
      _source: 'john.username' // will be replaced with the respective value from the source object
    }
  }
}

Example source object:

{
  john: {
    username: 'johndoe'
  }
}

Mapping:

// Using the objects defined above
MapJson.map(sourceObject, mappingObject);
/*
{
  name: 'John',
  data: {
    id: 123,
    username: 'johndoe'
  }
}
*/

Wildcards

The _source value can also contain wildcards:

MapJson.map(
// Source
{
  users: [
    { name: 'John' },
    { name: 'Peter' }
  ]
},
// Mapping object
{
  usernames: { _source: 'users.*.name' },
  firstUser: { _source: '*.0.name' }
});
/*
{
  usernames: ['John', 'Peter'],
  firstUser: 'John'
}
*/

Default values

_default can be used to return default values when the referenced value is not defined in the source object:

MapJson.map(
// Source
{},
// Mapping object
{
  fruit: {
    _source: 'fruits.apple.name',
    _default: 'apple'
  }
});
/*
{
  fruit: 'apple'
}
*/

Transform functions

By defining _transform, values can be processed by one or more transform functions:

MapJson.map(
// Source
{
  fruits: {
    apple: {
      name: 'apple'
    }
  }
},
// Mapping object
{
  fruit: {
    _source: 'fruits.apple.name',
    // toUpperCase is a reference to the function in the third parameter (see below)
    // The array represents the parameters passed to the transform function (see next example)
    _transform: { toUpperCase: [] }
  }
},
// Transform / condition functions
{
  toUpperCase: value => value.toUpperCase()
});
/*
{
  fruit: 'APPLE'
}
*/

It is also possible to pass parameters to transform functions or chain them:

MapJson.map(
// Source
{
  fruits: {
    apple: {
      name: 'apple',
      id: 123
    }
  }
},
// Mapping object
{
  fruit: {
    _source: 'fruits.apple.name',
    _transform: [
      { toUpperCase: [] },
      { append: ['_'] },
      // Parameters can also be referenced values
      { append: [{ _source: 'fruits.apple.id' }] }
    ]
  }
},
// Transform / condition functions
{
  append: (value, parameter) => `${value}${parameter}`,
  toUpperCase: value => value.toUpperCase()
});
/*
{
  fruit: 'APPLE_123'
}
*/

Conditions

_condition can be used to only map values when a certain condition is met. The syntax is identical to transform functions. However, instead of the result of the previous function, each transform function always receives the source(s) as the first parameter.

MapJson.map(
// Source
{
  fruits: {
    apple: {
      name: 'apple',
      id: 123
    },
    banana: {
      name: 'banana'
    }
  }
},
// Mapping object
{
  fruitName: {
    _source: 'fruits.apple.name',
    _condition: { trueCondition: [] }
  },
  fruitId: {
    _source: 'fruits.apple.id',
    // All conditions have to be met
    _condition: [{ trueCondition: [] }, { falseCondition: [] }],
    // When the condition is false, the default value will be used
    _default: 0
  },
  otherFruit: {
    _source: 'fruits.banana.name',
    _condition: [
      // Conditions can also be inverted
      { '!falseCondition': [] },
      // The input value is passed as the first parameter
      { 'equal': ['banana'] },
      // Conditions with '@' override the input value
      { '@equal': [10, 10] }
    ]
  }
},
// Transform / condition functions
{
  equal: (value, parameter) => value === parameter,
  falseCondition: () => false,
  trueCondition: () => true
});
/*
{
  fruitName: 'apple',
  fruitId: 0,
  otherFruit: 'banana'
}
*/

Nested mappings and conditional transforms

MapJson.map(
// Source
{
  fruits: {
    apple: {
      name: 'Apple',
      id: 123
    }
  }
},
// Mapping object
{
  fruitName: {
    // Source must always be defined to trigger mapping
    _source: '*',
    _transform: {
      '@returnDefined': [{
        _source: 'fruits.apple.name',
        _condition: { falseCondition: [] },
        _transform: { toLowerCase: [] }
      }, {
        _source: 'fruits.apple.name',
        _condition: { '@isEqual': [{ _source: 'fruits.apple.id' }, 123] },
        _transform: { toUpperCase: [] }
      }] 
    }
  }
},
// Transform / condition functions
{
  returnDefined: (param1, param2) => param1 || param2,
  isEqual: (param1, param2) => param1 === param2,
  falseCondition: () => false,
  trueCondition: () => true,
  toLowerCase: value => value.toLowerCase(),
  toUpperCase: value => value.toUpperCase()
});
/*
{
  fruitName: 'APPLE'
}
*/

Transform each

Instead of _transform, it is also possible to use _transformEach. If the source (or pre-process) resolves to an array, _transformEach is executed separately for each array value. Note: When _transform and _transformEach are defined, _transform is executed first.

Example of a more advanced mapping with partial array transformation and use of _transformEach:

MapJson.map(
// Source
{
  fruits: [{
    name: 'Apple',
    id: 1,
    color: 'red'
  }, {
    name: 'Lemon',
    id: 2,
    color: 'yellow'
  }]
},
// Mapping object
{
  fruits: {
    _source: '*',
    _transform: {
      '@toObjectArray': [{
        fruitName: { _source: 'fruits.*.name', _transformEach: { toUpperCase: [] } },
        fruitId: { _source: 'fruits.*.id' },
        fruitColor: { _source: 'fruits.*.color', _transformEach: { substr: [0, 1] } },
      }]
    }
  },
},
// Transform / condition functions
{
  toUpperCase: value => value.toUpperCase(),
  substr: (string, from, length) => string.substr(from, length),
  toObjectArray: inputObject => {
    // Uses lodash
    const createObjectByIndex = index => _.mapValues(inputObject, array => array[index]);
    const firstObjectValues = _.values(inputObject)[0] || [];
    return _.times(firstObjectValues.length, createObjectByIndex);
  }
}
);
/*
{
  fruits: [{
    fruitColor: 'r'
    fruitId: 1
    fruitName: 'APPLE'
  }, {
    fruitColor: 'y'
    fruitId: 2
    fruitName: 'LEMON'
  }]
}
*/

Pre-process function

It is possible to pre-process all mapped values, e.g., for type conversions:

MapJson.map(
// Source
{
  userId: 123
},
// Mapping object
{
  id: {
    _source: 'userId'
  },
},
// Transform / condition functions
null,
// Preprocess function
value => value.toString()
);
/*
{
  userId: '123'
}
*/

Note: When using multiple sources, each source is pre-processed separately. However, when a source resolves to an array, the pre-process function will receive the complete array, not separate values.

License

MIT