{"id":23040052,"url":"https://github.com/fastcodejava/readme","last_synced_at":"2026-02-04T15:05:11.007Z","repository":{"id":94009419,"uuid":"90671232","full_name":"fastcodejava/README","owner":"fastcodejava","description":"README.md","archived":false,"fork":false,"pushed_at":"2017-05-08T20:50:39.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-08T14:14:18.881Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fastcodejava.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-08T20:49:39.000Z","updated_at":"2017-05-08T20:49:39.000Z","dependencies_parsed_at":"2023-03-07T20:30:37.021Z","dependency_job_id":null,"html_url":"https://github.com/fastcodejava/README","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastcodejava%2FREADME","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastcodejava%2FREADME/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastcodejava%2FREADME/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastcodejava%2FREADME/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastcodejava","download_url":"https://codeload.github.com/fastcodejava/README/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246911498,"owners_count":20853657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-15T18:39:51.925Z","updated_at":"2026-02-04T15:05:10.881Z","avatar_url":"https://github.com/fastcodejava.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"jsonapter\n=====================\n\nTemplate Rules based JSON Transformer\n\n[![NPM](https://nodei.co/npm/jsonapter.png)](https://nodei.co/npm/jsonapter/)\n\n[![Build Status](https://travis-ci.org/amida-tech/jsonapter.svg)](https://travis-ci.org/amida-tech/jsonapter)\n[![Coverage Status](https://coveralls.io/repos/amida-tech/jsonapter/badge.png)](https://coveralls.io/r/amida-tech/jsonapter)\n\nThis library provides a template rules based formalism to describe JSON to JSON transformations declaratively.  This formalism is primarily designed for health data translation between various formats such as FHIR and CCDA.\n\n## Usage\n\nIn its most basic form JSON to JSON transformations are described by a template object where [`content`](#content) properties recursively describe destination keys, [`dataKey`](#dataKey) properties describe source keys, and [`value`](#value) properties describe formatting\n```js\nvar upper = function(input) {\n\treturn input ? input.toUpperCase() : null;\n};\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a.c'\n        },\n        dest_b: {\n            content: {\n                dest_b0: {\n                    value: upper,\n                    dataKey: 'b.c'\n                },\n                dest_b1: {\n                    value: upper,\n                    dataKey: 'd'\n                }\n            },\n            dataKey: 'a'\n        }\n    }\n};\n```\nAn engine instance is available from jsonapter and can be used to transform an `input` as described by the template\n```js\nvar bbj2j = require('jsonapter');\nvar j2j = bbj2j.instance();\n\nvar input = {\n    a: {\n        b: {\n            c: 'value_0'\n        },\n        c: 'value_2',\n        d: 'value_1'\n    }\n};\n\nvar r = j2j.run(template, input);\nconsole.log(r); // {dest_a: 'value_2', dest_b: {dest_b0: 'VALUE_0', dest_b1: 'VALUE_1'}}\n```\n\n## Standard Template Rules\n\nThe following are the list of all keys that have special meaning in template objects\n- [`dataKey`](#dataKey)\n- [`value`](#value)\n- [`content`](#content)\n- [`arrayContent`](#arrayContent)\n- [`constant`](#constant)\n- [`existsWhen`](#existsWhen)\n- [`existsEither`](#existsEither)\n- [`existsUnless`](#existsUnless)\n- [`dataTransform`](#dataTransform)\n- [`default`](#default)\n- [`multiple`](#multiple)\n- [`single`](#single)\n- [`firstOf`](#firstOf)\n- [`assign`](#assign)\n- [`ignoreDeep`](#ignoreDeep)\n- [`paramKey`](#paramKey)\n- [`arrayIndex`](#arrayIndex)\n- [`size`](#size)\n- [`template`](#template)\n- [`skip`](#skip)\n- [`output`](#output)\n\n\u003ca name=\"dataKey\" /\u003e\n#### `dataKey` rule\n\nThis rule selects a particular property of input. It can a `string`, `array` or `function`.\n```js\nvar template = {\n    dataKey: 'a'\n};\n\nvar r0 = j2j.run(template, {\n    a: 1,\n    b: 2\n});\nconsole.log(r0); // 1\n\nvar r1 = j2j.run(template, {\n    b: 2\n});\nconsole.log(r1); // null\n\n\nvar r2 = j2j.run(template, {\n    a: {\n        b: 2\n    }\n});\nconsole.log(r2); // {b: 2}\n```\n\nThe properties can be deep\n```js\nvar template = {\n    dataKey: 'a.b.c'\n};\n\nvar r0 = j2j.run(template, {\n    a: {\n        b: {\n            c: 'value'\n        }\n    }\n});\nconsole.log(r0); // 'value'\n\nvar r1 = j2j.run(template, {\n    a: 2\n});\nconsole.log(r1); // null\n```\n\nIf the property or any of the properties on the deep property is an array `dataKey` you can use jsonave\n```js\nvar jsonave = require('jsonave').instance;\n\nvar template = {\n    dataKey: jsonave('a.b[*].c')\n};\n\nvar r = j2j.run(template, {\n    a: {\n        b: [{\n            c: 'value_0'\n        }, {\n            d: 'value_1'\n        }, {\n            c: 'value_2'\n        }]\n    }\n});\nconsole.log(r); // ['value_0', 'value_2']\n```\nCurrently only one array on a deep property is supported.  Multiple arrays will result in array of arrays.\n\n`0` on a deep property is treated as a special case and selects the first element of the array\n```js\nvar template = {\n    dataKey: 'a.b.0.c'\n};\n\nvar r = j2j.run(template, {\n    a: {\n        b: [{\n            c: 'value_0'\n        }, {\n            d: 'value_1'\n        }, {\n            c: 'value_2'\n        }]\n    }\n});\nconsole.log(r); // 'value_0'\n```\n\n`dataKey` can be a function.  In particular JSONPath expressions are particularly useful and available from [jsonave](https://github.com/amida-tech/jsonave)\n```js\nvar jsonave = require('jsonave').instance;\nvar template = {\n    dataKey: jsonave('book[1:].price')\n};\n\nvar r = j2j.run(template, {\n    book: [{\n        price: 10\n    }, {\n        price: 20\n    }, {\n        price: 30\n    }]\n});\n\nconsole.log(r); // [20, 30]\n```\nA second [`context`](#context) parameter is also passed to `dataKey` functions.  By default this parameter is an empty object but that can be [overridden](#context).  This is useful to further customize JSONPath function.\n\n`dataKey` can be an array.  In that case the first deep property that evaluates to a value that is not `null` is selected\n```js\nvar template = {\n    dataKey: ['a.b', 'a.c']\n};\n\nvar r0 = j2j.run(template, {\n    a: {\n        b: 1,\n        c: 2\n    }\n});\nconsole.log(r0); // 1\n\nvar r1 = j2j.run(template, {\n    a: {\n        c: 3\n    }\n});\nconsole.log(r1); // 3\n\nvar r2 = j2j.run(template, {\n    a: {\n        d: 4\n    }\n});\nconsole.log(r2); // null\n```\n\n\u003ca name=\"paramKey\" /\u003e\n#### `paramKey` rule\n\nThis rule selects a particular property of params, which can be passed as a optional third parameter to the run function as shown below :\n```js\nvar template = {\n    paramKey: 'a'\n};\n\nvar r0 = j2j.run(template, {}, {\n    a: 1\n});\nconsole.log(r0); // 1\n\nThe `paramKey` value can be an object\n\nvar template = {\n    paramKey: 'paramObject'\n};\n\nvar r0 = j2j.run(template, {}, {\n    paramObject: {\n        a : {\n            b: \"test\"\n        }\n    }\n});\nconsole.log(r0);\n\n{\n   a : {\n          b: \"test\"\n   }\n}\n```\n\n\u003ca name=\"arrayIndex\" /\u003e\n#### `arrayIndex` rule\nThis rule is primarily used to get the index of the array. Optionally `start` can be given.\nWithout `start` it will be zero based as usual.\n\n```js\n\n      var template = {\n          content: {\n              cost: {dataKey: 'price'},\n              num: {arrayIndex: {}}\n          }\n      };\n\n      var r = j2j.run(template,\n          [{\n              price: 20\n          }, {\n              price: 30\n          }]);\n\nconsole.log(r); // // [{cost: 20, num: 0}, {cost: 30, num: 1}]\n```\n\nWith `start` :\n\n```js\n\n      var template = {\n          content: {\n              cost: {dataKey: 'price'},\n              num: {arrayIndex: {start: 1}}\n          }\n      };\n\n      var r = j2j.run(template,\n          [{\n              price: 20\n          }, {\n              price: 30\n          }]);\n\nconsole.log(r); // // [{cost: 20, num: 1}, {cost: 30, num: 2}]\n```\n\n\u003ca name=\"size\" /\u003e\nThis rule is primarily used to get the length of an array. It is also valid for length of string and object.\nIf it is in the context of an array the `size` will print the length of the array. If not it will check if it is in the same template with the `dataKey`.\n\n```js\n      var template = {\n          content: {\n              cost: {dataKey: 'price'},\n              num: {arrayIndex: {}}\n              total: {size: {}}\n          }\n      };\n\n      var r = j2j.run(template,\n          [{\n              price: 20\n          }, {\n              price: 30\n          }]);\n\nconsole.log(r); // // [{cost: 20, total:2, num: 0}, {cost: 30, total:2, num: 1}]\n```\n\n```js\n        var template = {dataKey: 'name', size: {}};\n        var r = j2j.run(template, {\n            name: 'USA'\n        });\n        //console.log(r); // 3\n        expect(r).to.deep.equal(3);\n```\n\n\n\u003ca name=\"template\" /\u003e\n#### `template` rule\n\nThis rule is primarily used to apply a nested template.\n```js\nvar nestedTemplate = {\n    value: function(input) {\n        return input.toUpperCase();\n    },\n    dataKey: 'b'\n};\n\nvar template = {\n    template: nestedTemplate,\n    dataKey: 'a'\n};\n\nvar r = j2j.run(template, {\n    a: {\n        b: 'value'\n    }\n});\nconsole.log(r); // 'VALUE'\n```\n\n\u003ca name=\"value\" /\u003e\n#### `value` rule\n\nThis rule is primarily used to format `input` or `input` property that is selected by `dataKey`.  In this case it is a function\n```js\nvar template = {\n    value: function (input) {\n        return input.toUpperCase();\n    },\n    dataKey: 'name'\n};\n\nvar r = j2j.run(template, {\n    name: 'joe'\n});\nconsole.log(r); // JOE\n```\n```js\nvar template = {\n    value: function (input) {\n        return input.toUpperCase();\n    }\n};\n\n\nvar r = j2j.run(template, 'joe');\nconsole.log(r); // JOE\n```\nOne can also use the parent inside the value function.\n\n```js\nvar template = {\n    value: function (input, parent) {\n        return parent.title.toUpperCase() + ' ' + input.toUpperCase();\n    },\n    dataKey: 'name'\n};\n\nvar r = j2j.run(template, {\n    name: 'joe',\n    title: 'mr'\n});\nconsole.log(r); // MR JOE\n```\n\n\nOne can also use the params to the value function.\n```js\nvar template = {\n    dataKey: 'name',\n    value: function (input, parent, params) {\n        return params.title[input.gender] + ' ' + input;\n    }\n};\n\nvar params = {title: { M: 'Mr', F: 'Ms'}};\n\nvar input = {name: 'Joe', gender: 'M'};\n\nvar r = j2j.run(template, input, params);\nconsole.log(r); // Mr Joe\n\nvar input1 = {name: 'Jane', gender: 'F'};\n\nvar r1 = j2j.run(template, input1, params);\nconsole.log(r1); // Ms Jane\n\n```\n\n\nThis rule can be used to return a primary data type\n```js\nvar template = {\n    value: 'names are classified',\n    dataKey: 'name'\n};\n\nvar r = j2j.run(template, {\n    name: 'joe'\n});\nconsole.log(r); // 'names are classified'\n```\n\nThis rule can be used to as lookup with `lookup:true`. When it is an object without `dataKey` we take it as literally.\nThe `value` should not be used as a nested template. If `dataKey` is provided one can use it for lookup as shown below:\n\n```js\nvar template = {\n    content: {\n         title: {\n            dataKey: \"gender\",\n            value: {\n                M: 'Mr',\n                F: 'Ms'\n             },\n             lookup: true\n            },\n         name : { dataKey: \"name\" }\n    }\n}\n\nvar input = {name: 'Joe', gender: 'M'};\n\nvar r = j2j.run(template, input);\n\nconsole.log(r); // { title: \"Mr\", name : \"Joe\" }\n\n\n```\n\n\n\u003ca name=\"content\" /\u003e\n#### `content` rule\n\nThis rule is used to describe a new object based on `input`.  The property keys of the `content` becomes the properties in the destination object.  The property values of `content` are primarily other templates.\nThis is an object and cannot be empty.\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    }\n};\n\nvar template = {\n    content: {\n        name: nameTemplate,\n        age: {\n            value: function (input) {\n                return 2015 - input;\n            },\n            dataKey: 'birthYear'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE',\n    birthYear: 1980\n});\nconsole.log(r); // {name: {last: 'DOE', first: 'JOE'}, age: 35}\n```\n\nThe `content` property values can also be formatting functions or primary data types which shortcuts the need to use `value` rule for those cases\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    }\n};\n\nvar template = {\n    content: {\n        type: 'Report',\n        title: function (input) {\n            return input.gender === 'M' ? 'Mr.' : 'Ms.';\n        },\n        name: nameTemplate,\n        age: {\n            value: function (input) {\n                return 2015 - input;\n            },\n            dataKey: 'birthYear'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE',\n    gender: 'M',\n    birthYear: 1980\n});\nconsole.log(r); // {type: 'Report', title: 'Mr.', name: {last: 'DOE', first: 'JOE'}, age: 35}\n```\n\nThe `content` property keys can be deep\n```js\nvar template = {\n    content: {\n        'name.last': {\n            dataKey: 'familyName'\n        },\n        'name.first': {\n            dataKey: 'givenName'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r); // {name: {last: 'DOE', first: 'JOE'}}\n```\n\n\u003ca name=\"arrayContent\" /\u003e\n#### `arrayContent` rule\n\nThis rule is similar to `content` but is used to describe an `array` instead of an `object` based on `input`.  The array elements of the `arrayContent` becomes the array elements in the destination object.  Otherwise the array elements of the `arrayContent` work identically to properties of the `content`\nThis is an array and cannot be empty.\n\n```js\nvar nameTemplate = {\n    arrayContent: [{\n        dataKey: 'familyName'\n    }, {\n        dataKey: 'givenName'\n    }]\n};\n\nvar template = {\n    content: {\n        name: nameTemplate,\n        age: {\n            value: function (input) {\n                return 2015 - input;\n            },\n            dataKey: 'birthYear'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE',\n    birthYear: 1980\n});\nconsole.log(r); // {name: ['DOE', 'JOE'], age: 35}\n```\n\n\u003ca name=\"constant\" /\u003e\n#### `constant` rule\n\nWhen values in `value` rule and property values in `content` rule are objects, they are assumed to be nested templates.  `constant` rule makes it possible to define a constant object within template\n```js\nvar template = {\n    content: {\n        codes: {\n            constant: {\n                'Y': 'yellow',\n                'R': 'red'\n            }\n        },\n        'color.back': {\n            dataKey: 'backgroundColor'\n        },\n        'color.fore': {\n            dataKey: 'foreGroundColor'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    backgroundColor: 'Y',\n    foreGroundColor: 'R'\n});\nconsole.log(r); // {codes: {Y: 'yellow', R: 'red'}, color: {back: 'Y', fore: 'R'}}\n```\n\nYou can also use primary data types in `constant` rule as alternatives to directly specifying them with `content` and `value` rules\n```js\nvar template = {\n    constant: 'CONST'\n};\n\nvar r = j2j.run(template, {\n    any: 'any'\n});\nconsole.log(r); // 'CONST'\n```\n\n\u003ca name=\"existsWhen\" /\u003e\n#### `existsWhen` rule\n\nThis rule must be a predicate or array of predicates. If the predicate evaluates to false, the template is ignored.  This rule is evaluated before any other rule on the same level.\nThe predicate can be a `function`, an `object` or a simple `property`. If it is an object or a simple property it works just like [iteratee](https://lodash.com/docs/4.16.3#iteratee) in lodash.\nThe property can be in the input or in the params.  It is to be noted that this feature is little different from the value function which is supplied with params as well as input.\nFor the value function the input and the params are available at the same time to the `function`.\n\n```js\nvar _ = require('lodash');\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a'\n        },\n        dest_b: {\n            dataKey: 'b',\n            existsWhen: _.partialRight(_.has, 'c')\n        },\n    },\n    existsWhen: 'public'\n};\n\nvar r0 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    public: true\n});\nconsole.log(r0.dest_a); // 'value_a'\nconsole.log(r0.dest_b); // undefined\n\nvar r1 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 0,\n    public: true\n});\nconsole.log(r1.dest_a); // 'value_a'\nconsole.log(r1.dest_b); // 'value_b'\n\nvar r2 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 0\n});\nconsole.log(r2); // null because public is not present\n\n\nvar r3 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b'\n},\n{\n    public: true,\n    c: 0\n}\n);\n\n//console.log(r3.dest_a); // 'value_a'\n//console.log(r3.dest_b); // 'value_b'\n\n```\n\nIf this rule is an array, each predicate in the array must evaluate to true\n\n```js\nvar _ = require('lodash');\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a'\n        },\n        dest_b: {\n            dataKey: 'b'\n        },\n    },\n    existsWhen: [_.partialRight(_.has, 'c'), _.partialRight(_.has, 'd')]\n};\n\nvar r0 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 'available'\n});\nconsole.log(r0); // null\n\nvar r1 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    d: 'available'\n});\nconsole.log(r1); // null\n\nvar r2 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 'available',\n    d: 'available'\n});\nconsole.log(r2.dest_a); // 'value_a'\nconsole.log(r2.dest_b); // 'value_b'\n```\n\u003ca name=\"existsEither\" /\u003e\n#### `existsEither` rule\n\nThis rule must be an array of predicates. If all the predicates evaluates to false, the template is ignored.  This rule is evaluated before any other rule on the same level.\nThe predicate can be a function, an object or a simple property. If it is an object or a simple property it works just like [iteratee](https://lodash.com/docs/4.16.3#iteratee) in lodash.\n\n```js\nvar _ = require('lodash');\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a'\n        },\n        dest_b: {\n            dataKey: 'b'\n        },\n    },\n    existsEither: [_.partialRight(_.has, 'c'), _.partialRight(_.has, 'd')]\n};\n\nvar r0 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 'available'\n});\nconsole.log(r0.dest_a); // 'value_a'\nconsole.log(r0.dest_b); // 'value_b'\n\n```\n\n\n\u003ca name=\"existsUnless\" /\u003e\n#### `existsUnless` rule\n\n This rule must be a predicate or array of predicates. If the predicate evaluates to true, the template is ignored.  This rule is evaluated before any other rule but existsWhen.\n\n```js\nvar _ = require('lodash');\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a'\n        },\n        dest_b: {\n            dataKey: 'b',\n            existsUnless: _.partialRight(_.has, 'c')\n        },\n    },\n    existsUnless: function (input) {\n        return input \u0026\u0026 input.private;\n    }\n};\n\nvar r0 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 0,\n    private: false\n});\nconsole.log(r0.dest_a); // 'value_a'\nconsole.log(r0.dest_b); // undefined\n\nvar r1 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b'\n});\nconsole.log(r1.dest_a); // 'value_a'\nconsole.log(r1.dest_b); // 'value_b'\n\nvar r2 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    private: true\n});\nconsole.log(r2); // null\n```\n\nIf this rule is an array, each predicate in the array must evaluate to true for the template to evaluate to `null`.\n\n```js\nvar _ = require('lodash');\n\nvar template = {\n    content: {\n        dest_a: {\n            dataKey: 'a'\n        },\n        dest_b: {\n            dataKey: 'b'\n        },\n    },\n    existsUnless: [_.partialRight(_.has, 'c'), _.partialRight(_.has, 'd')]\n};\n\nvar r0 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 'available'\n});\nconsole.log(r0.dest_a); // 'value_a'\nconsole.log(r0.dest_b); // 'value_b'\n\nvar r1 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    d: 'available'\n});\nconsole.log(r1.dest_a); // 'value_a'\nconsole.log(r1.dest_b); // 'value_b'\n\nvar r2 = j2j.run(template, {\n    a: 'value_a',\n    b: 'value_b',\n    c: 'available',\n    d: 'available'\n});\nconsole.log(r2); // null\n```\n\n\u003ca name=\"dataTransform\" /\u003e\n#### `dataTransform` rule\n\nThis rule transforms `input` so that existing templates can be reused. It can be a string, or an `object` (another jsonapter template) as well as a `function`.\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    }\n};\n\nvar template = {\n    content: {\n        name: {\n        \ttemplate: nameTemplate,\n\t\t\t    dataTransform: function(input) {\n\t\t\t\t    return {\n\t\t\t\t\t    familyName: input.lastName,\n\t\t\t\t\t    givenName: input.firstName\n\t\t\t\t    };\n\t\t\t  }\n\t\t},\n        age: {\n            value: function (input) {\n                return 2015 - input;\n            },\n            dataKey: 'birthYear'\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    lastName: 'DOE',\n    firstName: 'JOE',\n    birthYear: 1980\n});\nconsole.log(r); // {name: {last: 'DOE', first: 'JOE'}, age: 35}\n```\n\nIn the above example `dataTransform` can be a jsonapter template as shown below :\n```js\n\n    dataTransform: {\n        content: {\n           familyName: { dataKey: \"lastName\" },\n           givenName: { dataKey: \"firstName\" }\n       }\n    }\n```\n\n\n\n\u003ca name=\"default\" /\u003e\n#### `default` rule\n\nThis rule can be used to assign default values after templates are evaluated to be `null`\nThe `default` can be a `function` as well. If `function` one can use the `input`, `parent`, and `params` just like `value` as `function`.\n\n```js\nvar template = {\n    content: {\n        last: {\n            dataKey: 'familyName',\n            default: 'unknown'\n        },\n        first: {\n            dataKey: 'givenName',\n            default: function() {return 'unknown';}\n        },\n        title: {\n            dataKey: 'title',\n            default: function getTitle(input, parent, params) {\n                if (parent.gender === 'M') {\n                    return \"MR\";\n                } else if (parent.gender === 'F') {\n                    return \"MS\";\n                } else {\n                    return null;\n                }\n            }\n        }\n    }\n};\n\nvar r0 = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r0); // {last: 'DOE', first: 'JOE', title: null}\n\nvar r1 = j2j.run(template, {\n    familyName: 'DOE'\n});\nconsole.log(r1); // {last: 'DOE', first: 'unknown', title: null}\n\nvar r2 = j2j.run(template, {\n    givenName: 'JOE'\n});\nconsole.log(r2); // {last: 'unknown', first: 'JOE', title: null}\n\nvar r3 = j2j.run(template, {\n    familyName: 'DOE'\n    givenName: 'JOE',\n    gender: 'M'\n});\nconsole.log(r3); // {last: 'unknown', first: 'JOE', title: 'MR'}\n\n```\n\n\n\u003ca name=\"multiple\" /\u003e\n#### `multiple` rule\n\nThis rule can be used to change a template evaluted value into a one element array\n```js\nvar template = {\n    content: {\n        last: {\n            dataKey: 'familyName',\n        },\n        given: {\n            dataKey: 'givenName',\n            multiple: true\n        }\n    }\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r); // {last: 'DOE', given: ['JOE']}\n```\n\u003ca name=\"single\" /\u003e\n#### `single` rule\n\nThis rule can be used to select the first value of a template evaluated array.  This is especially useful for conditional JSONPath expression\n```js\nvar jsonave = require('jsonave').instance;\nvar template = {\n    dataKey: jsonave('book[?(@.id===\"AF20\")].price'),\n    single: true\n};\n\nvar r = j2j.run(template, {\n    book: [{\n        id: \"AA10\",\n        price: 10\n    }, {\n        id: \"AF20\",\n        price: 20\n    }, {\n        id: \"AB15\",\n        price: 30\n    }]\n});\n\nconsole.log(r); // 20\n```\n\n\u003ca name=\"firstOf\" /\u003e\n#### `firstOf` rule\n\nThis rule must be assigned to an array of other templates and selects the first one that does not evaluate to `null`\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    },\n    existsWhen: function (input) {\n        return input \u0026\u0026 input.familyName \u0026\u0026 input.givenName;\n    }\n};\n\nvar template = {\n    firstOf: [nameTemplate, {\n        dataKey: 'familyName'\n    }]\n};\n\nvar r0 = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r0); // {last: 'DOE', first: 'JOE'}\n\nvar r1 = j2j.run(template, {\n    familyName: 'DOE'\n});\nconsole.log(r1); // 'DOE'\n\nvar r2 = j2j.run(template, {\n    givenName: 'JOE'\n});\nconsole.log(r2); // null\n```\n\nYou can also include a primary data type as the last element to simulate a default\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    },\n    existsWhen: function (input) {\n        return input \u0026\u0026 input.familyName \u0026\u0026 input.givenName;\n    }\n};\n\nvar template = {\n    firstOf: [nameTemplate, 'UNKNOWN']\n};\n\nvar r0 = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r0); // {last: 'DOE', first: 'JOE'}\n\nvar r1 = j2j.run(template, {\n    familyName: 'DOE'\n});\nconsole.log(r1); // 'UNKNOWN'\n```\n\n\u003ca name=\"assign\" /\u003e\n#### `assign` rule\n\nThis rule accepts an array of other templates that generate object results and works similar to [lodash assign method](https://lodash.com/docs#assign).  `assign` rule is primarily used to reuse existing templates to obtain a new one.\nThis is an array and cannot be empty.\n```js\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'familyName'\n        },\n        first: {\n            dataKey: 'givenName'\n        }\n    }\n};\n\nvar template = {\n    assign: [{\n        content: {\n            id: function (input) {\n                return input.givenName[0] + input.familyName;\n            }\n        }\n    }, nameTemplate]\n};\n\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r); // {id: 'JDOE', last: 'DOE', first: 'JOE'}\n```\n\n\u003ca name=\"ignoreDeep\" /\u003e\n#### `ignoreDeep` rule\n\nThis rule can be used when dots in [content](#content) keys are part of the key rather than describing a path\n```js\nvar template = {\n    content: {\n        'name.last': {\n            dataKey: 'familyName'\n        },\n        'name.first': {\n            dataKey: 'givenName'\n        }\n    },\n    ignoreDeep: true\n};\n\nvar r = j2j.run(template, {\n    familyName: 'DOE',\n    givenName: 'JOE'\n});\nconsole.log(r); // {'name.last': 'DOE', 'name.first': 'JOE'}\n```\n\n## Prune Values\n\nFrom the instance we can pass a third object parameter, as options, with an array named as `pruneValues`, to drop all the keys from the final output which have any of the values represented by the strings present in `pruneValues` array. This can always be override by using [`default`](#default) rule.\nArray pruneValues can take a min of 1 to a max of 3 string based rule. Comes in handy if we need to enforce dirty check on the templates.\n\nAs of now values which can be pruned are:\n\n- `emptyString`\n- `emptyArray`\n- `NaN`\n\n```js\n\nvar bbj2j = require('jsonapter');\n\nvar options =   {pruneValues: ['emptyString', 'emptyArray', 'NaN']};\n\nvar j2j = bbj2j.instance(null,null,options);\n\n\nvar sampleInput = {\n    firstName: 'TIM',\n    lastName:'DOE',\n    middleName:'JOE',\n    familyName:'',\n    address:'',\n    age:NaN,\n    numbers:[],\n    friends:[],\n    groups:[1,2]\n};\n\nvar sampleTemplate = {\n    content: {\n        firstName: {\n            dataKey: 'firstName'\n        },\n        middleName: {\n            dataKey: 'middleName'\n        },\n        lastName: {\n            dataKey: 'lastName'\n        },\n        familyName: {\n            dataKey: 'familyName'\n        },\n        address: {\n            dataKey: 'address', default: \"\"\n        },\n        age: {\n            dataKey: 'age'\n        },\n        numbers:{\n            dataKey:'numbers', default:[]\n        },\n        friends:{\n            dataKey:'friends'\n        },\n        groups:{\n            dataKey:'groups'\n        }\n    }\n};\n\nvar r = j2j.run(sampleTemplate, sampleInput);\n\nconsole.log(r); // {\"firstName\": \"TIM\", \"middleName\": \"JOE\", \"lastName\": \"DOE\", \"address\": \"\", \"numbers\": [], \"groups\": [1,2]}\n```\n\n\u003ca name=\"skip\" /\u003e\n#### `skip` rule\n\nThis rule is used to skip a template.\n\n```js\nvar nestedTemplate = {\n    dataKey: 'b',\n    skip: true\n};\n\nvar template = {\n    template: nestedTemplate,\n    dataKey: 'a'\n};\n\nvar r = j2j.run(template, {\n    a: {\n        b: 'value'\n    }\n});\nconsole.log(r); // null\n```\n\n\n\u003ca name=\"output\" /\u003e\n#### `output` rule\n\nThe `output` tag is there to modify final result. It can be either `string`, `boolean`, `number`, `object` or `function`.\nWhen it is a function it's first argument is the `result` of the template as shown below :\n\n```js\n\n{\n  dataKey: 'name',\n  output: function(result, input, parent, params) {\n    // return some other result\n  }\n\n}\n\n```\n\nIt is almost similar to the `value` as `function` but unlike `value` it is not an action key.\nThe `value` tag cannot be present along with other actionKeys e.g `content`, `arrayContent` etc.\nThe `output` tag can be specified by simply saying `{output: string}` or `output: {type: `string`}.\n\nIf output is a string then more options are available e.g `split`, `substring`, `upperCase`, `lowerCase`, etc.\n\n| Type      |   options    |   Format\n----------- |:------------:|:------------------------------\n| String    |   split      |  split: {separator(optional): \"-\"}, if no separator it will be white space\n| String    |   trim       |  trim: true\n| String    |   substring  |  substring: {start(optional): 1, end(optional): 5}\n| String    |   upperCase  |  upperCase: true\n| String    |   lowerCase  |  lowerCase: true\n| String    |   prefix     |  prefix: \"a\"\n| String    |   suffix     |  suffix: \"b\"\n| boolean   |   suffix     |  suffix: \"b\"\n\n\n## Errors\n\nThis library will throw `Error` in some cases, e.g. if [`content`](#content) is provided but it is an array or it is empty.\nThis can be avoided by creating a `jsonapter` `instance` with `options` as `instance (null, null, {mode: null})`.\nBy default, `mode` is `strict`.\n\n\n## Overrides\n\nEach engine instance `j2j` contains all the implementation details as functions in the following keys:\n- `run`\n- `content`\n- `assign`\n- `firstOf`\n- `constant`\n- `arrayIndex`\n- `template`\n- `size`\n- `value`\n- `runForArray`\n- `evaluateDataKey`\n- `evaluateValue`\n- `actionKeys`\n- `dataKeyToInput`\n- `dataKeyArrayToInput`\n- `context`\n\n`run` is the entry point. `content`, `arrayContent`, `value`, `size`, `template`, `arrayIndex`, `constant`, `firstOf` and `assign` are called action keys and listed in `actionKeys` array.\nOnly one of `actionKeys` can appear on a template on the same level. None of these keys are designed to be overridden except `context`.  However you can add additional functionality by adding new data and action keys.\n\n### Overrides To Existing Keys\n\nAlthough in principle any of the implementation keys can be overridden, only `context` is designed as such.\n\n\u003ca name=\"context\" /\u003e\n#### `context` Override\n\nWhen `dataKey` is a function this parameter is passed as the second parameter.  By default `context` is an empty object.  You can specify any property to be used by the `dataKey` function.  In particular [jsonave](https://github.com/amida-tech/jsonave) library allows functions in JSONPath expressions which can be specified with this key\n\n```js\nvar override = {\n    context: {\n        round: function(obj) {\n            return Math.round(obj);\n        }\n    }\n};\n\nvar j2j_dkfno = bbj2j.instance(override, override);\n\n\nvar jsonave = require('jsonave').instance;\nvar template = {\n    dataKey: jsonave('book[:].price.round()')\n};\n\nvar r = j2j_dkfno.run(template, {\n    book: [{\n        price: 10.3\n    }, {\n        price: 22.2\n    }, {\n        price: 31.9\n    }]\n});\n\nconsole.log(r); // [10, 22, 32]\n```\n\n### Additional Action Keys\n\nThe functionality of templates can be customized by adding additional action keys\n```js\nvar meds = {\n    'aspirin': {\n        id: 1\n    },\n};\n\nvar override = {\n    meds: meds,\n    external: function (template, input) {\n        var te = template.external;\n        if (!input) {\n            return null;\n        }\n        var external = this.meds[input];\n        if (external) {\n            return external.id;\n        } else {\n            var newId = Object.keys(meds).length + 1;\n            meds[input] = {\n                id: newId\n            };\n            return newId;\n        }\n    }\n};\n\nvar j2j_od_e = bbj2j.instance(override, ['external']);\n\nvar nameTemplate = {\n    content: {\n        last: {\n            dataKey: 'lastName'\n        },\n        first: {\n            dataKey: 'firstName'\n        }\n    }\n};\n\nvar template = {\n    content: {\n        name: nameTemplate,\n        meds: {\n            external: {},\n            dataKey: 'meds'\n        }\n    }\n};\n\nvar r = j2j_od_e.run(template, {\n    lastName: 'Doe',\n    firstName: 'Joe',\n    meds: ['claritin', 'aspirin', 'albuterol']\n});\nconsole.log(r); // {name: {last: 'Doe', first: 'Joe'}, meds: [2, 1, 3]}\n\nconsole.log(meds); // {aspirin: {id: 1}, claritin: {id: 2}, albuterol: {id: 3}}\n```\nHere we added `external` to `actionKeys`.  Note that for this simple example, `external` is assigned to an empty object but in general it can be anything including other templates.  You can `run` the templates by `this.run(te, input)` where `te` is the value of `external` as demontrated above.\n\n## License\n\nLicensed under [Apache 2.0](./LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastcodejava%2Freadme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastcodejava%2Freadme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastcodejava%2Freadme/lists"}