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

metamorphosi

v0.8.2

Published

Transform jsons using templates

Downloads

567

Readme

metamorphosi

Node.js module that is used to transform input - $ or $1 - jsons based on templates

Syntax

Builder

const { getTransform } = require('metamorphosi');
const transform = getTransform(template, options);
transform($, $1);

Parameters

template a template is given as parameter. The possible values are described bellow in Template possible values

options? an object containing

  • dropValues? (default: [null, undefined, '']), Values that will be dropped from output
  • cb? (default x => x) a tranformating function that will be used in all output values.

Return

a function that when given two inputs will tranform them and produced 1 output based on the template

Transform with all options

const {transform} = require('metamorphosi');
const transform(template, options)

The builder given is a convenient wrapper of the above method to easily reuse it with the same template and options.

Parameters

template a template is given as parameter. The possible values are described bellow in Template possible values

options an object containing

  • dropValues? (default: [null, undefined, '']), Values that will be dropped from output
  • cb? (default x => x) a tranformating function that will be used in all output values.
  • $ the input to be tranformed
  • $1 a second input to be transformed

Return

tranformed inputs based on the template and $, $1. The output type is very similar to the template given

Usage

const {getTransform} = require('metamorphosi');

/** A template example */
const template = {
  simpleString:'string ',
  simpleNumber: 100,
  simpleBoolean: true,
  simpleArray: [1,2,3],
  path: '$.a.b.c',
  'arrayTransformed[$.array]': { a: '$.b', index: '$.$index', parentValue: '$..a.b.c', array: '$.$array'},
  simpleObject: {
    pathFromAlternativeInput: '$1.a.b'
  }
}

/** a cb example */
function cb(input){
  if(typeof input ==='string') return input.trim();
  return input;
}

/**
* The default dropValues used if not overwritten.
* - Any value in this array will be removed.
* - Empty arrays will be removed
* - Empty objects will also be removed
*/
const dropValues = [null, undefined, ''];
const transform = getTransform(template, {dropValues, cb})

> transform({a:{b:{c:' a value '}}, array: [{b: ' test '}, {b: 'another test'}]}, {a:{b:'alternative value '}})
/* {
  "simpleString": "string",
  "simpleNumber": 100,
  "simpleBoolean": true,
  "simpleArray": [1, 2, 3],
  "path": "a value",
  "arrayTransformed": [
    {
      "a": "test",
      "index": 0,
      "parentValue": "a value",
      "array": [{"b": " test "}, {"b": "another test"}]
    },
    {
      "a": "another test",
      "index": 1,
      "parentValue": "a value",
       "array": [{"b": " test "}, {"b": "another test"}]
    }
  ],
  "simpleObject": {
    "pathFromAlternativeInput": "alternative value"
  }
}
*/

// This is the same as
const {transform} = require('template-transformer');

transform(template, {
  dropValues,
  cb,
  $:{a:{b:{c:' a value '}}, array: [{b: ' test '},
  $1:{b: 'another test'}
});

// getTrasform is usefull if you need to use trasform many times as it reuses
// the same template, options

Template possible values

As seen in the respective types the template can have 7 different type of values:

LITERAL_NUMBER

A literal number in the template will always be preserved in the resulting output

eg:

transform(1, {}); //1

unless it exists in dropValues

eg:

transform(0, { dropValues: [0] }); // undefined

LITERAL_STRING

Similarly a literal string will be always preserved. By default empty string are always dropped:

eg:

transform('foo', {}); // 'foo'
transform('', {}); // undefined
transform('', { dropValues: [] }); // ''

LITERAL_BOOLEAN

Similarly the use of boolean values are preserved no matter the input

eg:

transform(true, {}); // true
transform(false, {}); // false

JSON_PATH

With the use of $ or $1 you can access any value from the given json

eg:

transform('$.foo.bar', { $: { foo: { bar: 'value' } } }); // 'value'

// accessing arrays:
transform('$.foo.0.bar', { $: { foo: [{ bar: 'value' }] } }); // 'value'

OBJECT

All the above examples are pretty simple. Getting a literal value or a single value by accessing an input would be pretty simple without a module. The power of this module is with tranforming to objects. The values of a key can be any of the values of a template including another object. There are 5 differnt types of keys that can exist in an object template:

SIMPLE

A simple string key

eg:

transform({ value: '$.foo' }, { $: { foo: 'bar' } }); // { value: 'bar' }

TYPE_ARRAY

One common need is to iterate an inputs array and create a different array in the output.

eg:

transform({ 'value[$.foo]': '$.0' }, { $: { foo: ['bar', 'foo'] } }); // { value: [ 'b', 'f' ] }

DUPLICATE

There is a common need to create an array from 2 or more sources from the input json. To address this need you can use keys suffixed with .$1-9

eg:

transform(
  { 'value.$1': ['a', 'b'], 'value[$.foo].$2': '$.0', 'value.$3': '$.array' },
  { $: { foo: ['bar', 'foo'], array: ['c', 'd'] } }
); // { value: [ 'a', 'b', 'b', 'f', 'c', 'd' ] }

Note however that if a duplicate key value is not an array, this will overwrite the previous array with a non array

TEMPLATE

You can use a key value from the input

eg:

transform({ ['$.foo']: 'foo' }, { $: { foo: 'bar' } }); // { bar: 'foo' }

IF

Sometimes you don't want an object to be included if some keys are missing. This is easily accomplished using the $if key

eg:

transform({ ['$.foo']: 'foo', a: '$.bar', $if: ['a'] }, { $: { foo: 'bar' } }); // undefined
transform({ ['$.foo']: 'foo', a: '$.bar', $if: ['a'] }, { $: { foo: 'bar', bar: 'bar' } }); // { bar: 'foo', a: 'bar' }

In addition to keys, the $\if array can contain functions. If at least one function returns false, the object won't be included in the final result.

eg:

transform({ ['$.foo']: 'foo', a: '$.bar', $if: [$ => false] }, { $: { foo: 'bar' } }); // undefined
transform({ ['$.foo']: 'foo', a: '$.bar', $if: [$ => $.bar.length > 0] }, { $: { foo: 'bar', bar: 'bar' } }); // { bar: 'foo', a: 'bar' }
transform({ ['$.foo']: 'foo', a: '$.bar', $if: [(_, $1) => !$1.erase] }, { $: { foo: 'bar', bar: 'bar' }, $1: { erase: true } }); // undefined

KEEP

Sometimes you want an object to be included even if it is empty. By default metamorphosi will drop empty objects. If you want to keep empty objects you can use the $keep:true special key.

eg:

transform({ $keep:true }, { }); // {}

Keep can also be used inside arrays to ensure that if the array is empty after the transformation, it is not removed from the end result

eg:

transform({ a: ['$keep', undefined, null] }, { }); // {a: []} 

ARRAY

As seen in some examples of object you can directly use arrays as deplates. The values of the array can be a valid template value

eg:

transform([1, '1', true, () => 'function', '$.foo', { foo: '$.foo' }, ['array']], { $: { foo: 'bar' } }); // [ 1, '1', true, 'function', 'bar', { foo: 'bar' } ]

FUNCTION

You can also use callbacks that take as an input ($,$1)

eg:

transform($ => $.foo, { $: { foo: 'bar' } }); // 'bar'

Error Handling

All errors are cought by the library. Even in JSON paths (eg null pointer exceptions) or errors in Function callbacks. In cases an error occurs the template will resolve into an undefined value that will be removed (Unless dropValues is overwritten).

$1

Sometimes it is useful to have a second maybe configuration object that can impact the output. An example can be when transforming an api response eg. $ and want to use some configuration eg. $1 to differentiate the output.

About

This work was inspired by jsonpath-object-transform and my work @Workable. More than 6 years of experience transforming jsons using templates and code resulted in this module. It tries to solve most common issues and difficulties people have when working with templates. This module concept was initially developed during my flight to Brussels from Athens and back.