extended-shape-json
v1.2.6
Published
util module for json object transformations
Downloads
6
Maintainers
Readme
Forked from https://github.com/ansteh/shape-json
Extended Shape-JSON
Shape-json package from ansteh, but with adding more fexibility and features :
- Ignore unknown properties
- Multiple arguments operations
- Advanced arguments
- Small fixes
- More operations keywords
eval
Compute value from complex inputor
Select the first non-null or non-indefinite occurrenceforeach
Iterations simplerif
Conditional value or nested object
Parse input by a scheme defined as json
Consider you want to transform the below json object, into a nested json object we used to from MEAN stack.
var input = [
{pid: 1, contributor: 'jdalton', projectID: 1, projectName: 'lodash'},
{pid: 1, contributor: 'jdalton', projectID: 2, projectName: 'docdown'},
{pid: 1, contributor: 'jdalton', projectID: 3, projectName: 'lodash-cli'},
{pid: 2, contributor: 'contra', projectID: 4, projectName: 'gulp'},
{pid: 3, contributor: 'phated', projectID: 4, projectName: 'gulp'},
]
Instead of producing a lot of duplicated code to accomplish such transformations. We declare a scheme as a json object:
var scheme = {
"$group[contributors](pid)": {
"id": "pid",
"name": "contributor",
"$group[projects](projectID)": {
"id": "projectID",
"name": "projectName"
}
}
};
console.log(shape.parse(input, scheme));
This is what you get:
{
"contributors": [
{
"id": 1,
"name": "jdalton",
"projects": [
{
"id": 1,
"name": "lodash"
},
{
"id": 2,
"name": "docdown"
},
{
"id": 3,
"name": "lodash-cli"
}
]
},
{
"id": 2,
"name": "contra",
"projects": [
{
"id": 4,
"name": "gulp"
}
]
},
{
"id": 3,
"name": "phated",
"projects": [
{
"id": 4,
"name": "gulp"
}
]
}
]
}
Flexible syntax
Even if it is less useful, you have the possibility to modify the text of the operations by keeping some important keywords. This allows you to get a clearer model.
let template = {
"currentTopic": "topic",
"$foreach item of (data.books) push it on [library] section": {
"bookIndex": "index",
"bookAuthor": "author",
"bookName": "name"
}
}
Operators
foreach
This operator allows you to parse each element of a given array as input to another array with a new structure (defined in the template).
/* Input */
let input = {
topic: "sample of books",
data: {
books: [
{ index: 1, author: 'bart', name: 'title1' },
{ index: 2, author: 'arya', name: 'title2' },
{ index: 3, author: 'gwen', name: 'title3' },
{ index: 4, author: 'arya', name: 'title4' },
{ index: 5, author: 'lara', name: 'title5' }
]
}
}
/* Template */
let template = {
"currentTopic": "topic",
"$foreach[library](data.books)": {
"bookIndex": "index",
"bookAuthor": "author",
"bookName": "name"
}
}
console.log(shape.parse(input, template));
/*
{
currentTopic: 'sample of books',
library: [
{ bookIndex: 1, bookAuthor: 'bart', bookName: 'title1' },
{ bookIndex: 2, bookAuthor: 'arya', bookName: 'title2' },
{ bookIndex: 3, bookAuthor: 'gwen', bookName: 'title3' },
{ bookIndex: 4, bookAuthor: 'arya', bookName: 'title4' },
{ bookIndex: 5, bookAuthor: 'lara', bookName: 'title5' }
]
}
*/
eval
Templates allows "eval" keyword to be used in order to generate complex conditions from piece of code. Currently, you can get values from your input data with the "$value" operator, where a simple example is shown just below.
let input = {
name: 'marc',
age: 25
}
let template = {
"$eval[isMarc]": "$value(name) === 'marc'",
"$eval[description]": "let a = $value(age); let n = $value(name); if(a > 18) n + ' is an adult'; else n + ' is a child'"
}
console.log(shape.parse(input, template));
/*
{
"isMarc": true,
"description": "marc is an adult"
}
*/
or
The templates allow you to use the keywords "or" to select the first non-null or non-indefinite occurrence. This is useful when you can receive multiple entries whose structures may differ.
let input1 = {
name: 'marc'
}
let input2 = {
firstname: 'marc'
}
let input3 = {
lastname: 'marc'
}
let template = {
"$or[name]": [ 'name', 'firstname' ] // if "name" property is not defined, then we take "firstname" property
}
console.log(shape.parse(input1, template)); // { name: 'marc' }
console.log(shape.parse(input2, template)); // { name: 'marc' }
// If there is no valid property given, the "or" operator return "undefined", that result in ignoring template current property in the result
console.log(shape.parse(input3, template)); // { }
if
This operator allows you to make a value or a nested object conditional, according to a custom condition statement.
let input1 = {
a: true,
c: { 'property1': 1 }
}
let input2 = {
a: true,
b: 1,
c: { }
}
let template = {
"$if(this.a == true && this.b == 1 && this.c !== null)[abcExists]": true
}
console.log(shape.parse(input1, template)); // {}
console.log(shape.parse(input2, template)); // { "abcExists": true }
Parsing nested json objects as input
let scheme = {
"$mirror(id)": {
"name": "event.name"
}
};
let nestedInput = [{
id: 1,
event: {
name: 'lookup',
}
},{
id: 2,
event: {
name: 'add',
}
}];
console.log(shape.parse(nestedInput, scheme));
[ { "name": "lookup" }, { "name": "add" } ]
Another example:
var scheme = {
"$mirror[projects](projectID)": {
"project": {
"id": "projectID",
"name": "projectName"
}
}
};
console.log(shape.parse(input, scheme));
{
"projects": [
{
"project": {
"id": 1,
"name": "lodash"
}
},
{
"project": {
"id": 2,
"name": "docdown"
}
},
{
"project": {
"id": 3,
"name": "lodash-cli"
}
},
{
"project": {
"id": 4,
"name": "gulp"
}
}
]
}
The same example as above as Array:
var scheme = {
"$mirror(projectID)": {
"project": {
"id": "projectID",
"name": "projectName"
}
}
};
console.log(shape.parse(input, scheme));
[
{
"project": {
"id": 1,
"name": "lodash"
}
},
{
"project": {
"id": 2,
"name": "docdown"
}
},
{
"project": {
"id": 3,
"name": "lodash-cli"
}
},
{
"project": {
"id": 4,
"name": "gulp"
}
}
]
Assign default values by scheme
var simpleAssignScheme = {
"id": "pid",
"$set[active]": true // true in all objects
};
console.log(shape.parse(input, simpleAssignScheme));
{ "id": 1, "active": true }
Extend parse method with own operation
shape.define('growth', function(operation, provider, scheme, helpers){
var parse = helpers.parse;
var modifiedProvider = provider.map(function(point){
point.rate *= 100;
return point;
});
return parse(modifiedProvider, scheme);
});
var scheme = {
"$growth[growth]": {
"$mirror[rates]": {
"name": "name",
"percent": "rate"
}
}
};
var input = [
{
"name": "test1",
"rate": 0.1
},{
"name": "test2",
"rate": 0.2
}
];
var result = shape.parse(input, scheme);
//result equals:
{
growth: {
rates: [
{
"name": "test1",
"percent": 10
},{
"name": "test2",
"percent": 20
}
]
}
}
Create a scheme as object.
var scheme = shape.scheme()
.mirror({ id: 'pid', last_name: 'lastName' })
.indexBy('id');
Apply a scheme.
var inputs = [{
pid: 1,
lastName: 'Stehle',
firstName: 'Andre'
},{
pid: 2,
lastName: 'lastname',
firstName: 'firstname'
}];
console.log(scheme.form(inputs));
/*
{
1:{
id: 1,
last_name: 'Stehle'
},
2:{
id: 2,
last_name: 'lastname'
}
}
*/
API Documentation
mirror a collection
Mirror a json by a scheme.
var input = {
pid: 1,
lastName: 'Stehle',
firstName: 'Andre'
};
var scheme = {
id: 'pid',
last_name: 'lastName',
};
console.log(shape.mirror(input, scheme));
/*
{
id: 1,
last_name: 'Stehle'
}
*/
var inputs = [{
pid: 1,
lastName: 'Stehle',
firstName: 'Andre'
},{
pid: 2,
lastName: 'lastname',
firstName: 'firstname'
}];
console.log(shape.mirror(inputs, scheme));
/*
[{
id: 1,
last_name: 'Stehle'
},{
id: 2,
last_name: 'lastname'
}]
*/
indexing
Index an Array by a key.
var inputs = [{
id: 1,
last_name: 'Stehle'
},{
id: 2,
last_name: 'lastname'
}];
console.log(shape.indexBy(inputs, 'id'));
/*
{
1:{
id: 1,
last_name: 'Stehle'
},
2:{
id: 2,
last_name: 'lastname'
}
}
*/
chaining
Chaining previous examples.
var inputs = [{
pid: 1,
lastName: 'Stehle',
firstName: 'Andre'
},{
pid: 2,
lastName: 'lastname',
firstName: 'firstname'
}];
var result = shape.chain(inputs)
.mirror(scheme)
.indexBy('id')
.collection;
console.log(result);
/*
{
1:{
id: 1,
last_name: 'Stehle'
},
2:{
id: 2,
last_name: 'lastname'
}
}
*/
Related
- shape-array - Convert array to json object
- difference-json - Prompt the diffrence of two json objects
License
MIT © Andre Stehle