A new way to transform JSON object with a JSON stylesheet. It's like XSL/XML but only with JSON.
http://inist-cnrs.github.io/jbj-playground/
With npm do:
$ npm install jbj
Use mocha to run the tests.
$ npm install
$ npm test
Render input
with stylesheet
.
var JBJ = require('jbj'),
JBJ.render({ "truncate" : 3 }, "1234", function(err, out) {
console.log(out);
});
// Output : 123
Variable can be set using $
plus a dot notation path.
The set value can only be a JBJ expression (not a JSON literal).
Input:
{
"a": {
"b": {
"c": 1
},
"d": "Second"
}
}
Stylesheet:
{
"$x" : {
"get": "a.b.c"
},
"$y.y1.y2" : {
"get": "a.d"
}
}
Output:
{
"a": {
"b": {
"c": 1
},
"d": "Second"
},
"x": 1,
"y": {
"y1": {
"y2": "Second"
}
}
}
Alertative mode to use JBJ actions. You can inject in stylesheet
the input
.
Injections are identified by a prefix and suffix in the key.
The prefix and the suffix are the less-than sign <
.
Prefix inject the result of a JBJ action in the current scope.
Suffix inject the result of a JBJ render in the current key.
var JBJ = require('jbj'),
JBJ.render({ "<truncate" : 3 }, "1234", function(err, out) {
console.log(out);
});
// Output : 123
var input = {
key : "hello"
}
var stylesheet = {
"obj" : {
"<get" : "key",
upcase: true
}
};
// output : { obj : "HELLO" }
var input = {
key : "hello"
}
var stylesheet = {
"obj" : {
"keyword<" : {
get : "key",
upcase: true
}
}
};
// output : { obj : { keyword : "HELLO" } }
Add a function to fetch data for a specific protocol
JBJ.register('http:', function request(urlObj, callback) {
var buf = ''
, req = require('http').get(urlObj, function(res) {
if (res.statusCode !== 200) {
return callback(new Error('HTTP Error ' + res.statusCode));
}
res.setEncoding('utf8');
res.on('data', function (chunk) {
buf += chunk.toString();
});
res.on('error', callback);
res.on('end', function() {
callback(null, buf);
});
});
req.on('error', callback);
});
List all available actions.
var JBJ = require('jbj'),
console.log(JBJ.getActions());
// Output : ['get', 'set', 'expect' ...]
Get the statement function for an action name.
var JBJ = require('jbj'),
var func = JBJ.getFilter('append');
func('Hello', 'World' , function(err, output) {
console.log(output)
})
// Output : HelloWorld
Adding filters/actions for external module. see the avaible modules here : https://www.npmjs.com/browse/keyword/jbj
var JBJ = require('jbj'),
JBJ.use(require('jbj-numerical'));
JBJ.use(require('jbj-ist'));
JBJ.use(require('jbj-rdfa'));
Warning: the method has change since v4.0
A stylesheet is a JSON object where each key is an action. The actions are divided into modules (since v4.0):
- basics: all the basic actions for JBJ (debug, default, extend, set, get, add, expect, foreach, select, cast, mask, trim, required, assert, breakif, inject, render, compute)
- ejs: mainly the filters borrowed from EJS (first, last, capitalize, downcase, upcase, slug, sort, sort_by, size, max, min, plus, minus, times, dividedBy, join, truncate, shift, truncateWords, replace, prepend, append, reverse, flatten, deduplicate, remove, sum, slug)
- parse: file format conversion, through parsing (csv, parseCSV, parseCSVFile, json, parseJSON, xml, parseXML)
- template: template, templateURL
- array: complex actions implying arrays (mapping, mappingVar, zip, array2object, arrays2objects, coalesce, substring, getindex, getindexvar)
- rdfa: generate HTML+RDFa from a JSON-LD (getJsonLdField, style, class, tag, toHtml)
- nlp: natural language processing (anglicize, countCharacters, countWords, tokenize, metaphone)
- numerical: numerical text processing (floatprint, loselose, pearson, sdbm, fnv1a, murmur3, distincter, reseter)
- jsonld: facilitate the generation of JSON-LD from JSON (context, jsonld)
The modules you can use by defaults are basics
and ejs
.
To use another module, first install it via npm:
$ npm install jbj-array
then declare its use via:
JBJ.use(require('jbj-array'));
Note:
basics
andejs
modules are distributed with thejbj
package, and used by default: you can use their actions without any further declaration. However,parse
,template
, andarray
, which were parts of the pre-3.0 versions of JBJ are now separate packages (simply addjbj-
before the modules names to get their matching packages).
- module: basics
Set value and ignore input
var stylesheet1 = {
"set": "value"
};
var stylesheet2 = {
"set": ["value", "value", "value"]
};
var stylesheet3 = {
"set": {
"a": 1,
"b": 2
}
};
- module: basics
- aliases : find , path
Get value in input with some paths (with dot notation style)
var stylesheet1 = {
"set": {
"a" : {
"b" : {
"c" : "Yo"
}
}
},
"get": "a.b.c"
};
// output : Yo
var stylesheet2 = {
"set" : {
"a" : {
"b" : 1,
"c" : 2,
"d" : 3
}
},
"get": ["a.b", "a.c", "a.d"]
};
// output : [1, 2, 3]
- module: basics
Fix value if input is not set
var stylesheet = {
var stylesheet = {
"default": "value"
};
};
- module: basics
- aliases : fetchURL, $?
Stylesheet can contain a reference to data source. Source can be a file or an URL. By default, only the file: protocol is supported. Add your own protocol with register
var stylesheet_1 = {
"fetch" : "https://raw.githubusercontent.com/castorjs/node-jbj/master/package.json",
"$name" : {
"upcase": true
},
"$main": {
"upcase": true
}
};
var stylesheet_2 = {
"$name" : {
"fetch" : "file://" + path.resolve(__dirname, '../dataset/1.json'),
"parseJSON" : true,
"path": "name"
},
"$main": {
"fetch" : "file://" + path.resolve(__dirname, '../dataset/1.json'),
"parseJSON" : true,
"path": "main",
}
};
- module: basics
Add a key/value pair into the input object.
{
"input": { },
"stylesheet": {
"add": ["tag", "span"]
},
"expected": {
"tag": "span"
}
}
{
"input": {
"content": "not empty"
},
"stylesheet": {
"add": ["tag", "span"]
},
"expected": {
"content": "not empty",
"tag": "span"
}
}
- module: basics
Set default key/values for the input object: when a key is not present in the input object, it is set the value given in the argument object.
{
"input": {
"a": 3
},
"stylesheet": {
"expect": {
"a": 1,
"b": 2
}
},
"expected": {
"a": 3,
"b": 2
}
}
{
"stylesheet": {
"expect": {
"a": 1,
"b": 2
}
},
"expected": {
"a": 1,
"b": 2
}
}
- module: basics
Return a new Object with JBJ.inject.
- module: basics
Return a new Object with JBJ.render.
- module: basics
Compute an expression with all variables of the input. Use the filtrex syntax.
Note : this
variable contains input
var stylesheet = {
"set" : {
"a" : 20,
"b" : 3,
"c" : 5,
"d" : 8
},
"$x" : {
"compute#1": "a / b",
"compute#2": "round(this)",
"cast": "number"
},
"$y" : {
"path": "b",
"cast": "number"
},
"$z" : {
"compute": "x + y",
}
};
// output : 10
- module: basics
Print input with console.log
var stylesheet = {
"set": "value",
"debug": true
};
// output: value
- module: basics
Apply stylesheet on all elements of input
var stylesheet1 = {
"set": ["value", "value", "value"]
"foreach" : {
"upcase" : true
}
};
// output : ["VALUE", "VALUE", "VALUE"]
var stylesheet2 = {
"set": [
{ "b" : "x" },
{ "b" : "y" }
],
"foreach" : {
"get": "b",
"upcase" : true
}
};
// output : ["X", "Y"]
var stylesheet3 = {
"set": [
{ "b" : "x" },
{ "b" : "y" }
],
"foreach" : {
"$b" : {
"get": "b",
"upcase" : true
}
}
};
// output : [ { "b" : "X" }, { "b" : "Y" } ]
- module: basics
- aliases : extendWith
Extend input with another object
var stylesheet = {
"set": {
"a" : 1
},
"extend" : {
"b" : 2
}
};
// output : { a: 1, b: 2}
- module: basics
Peck element(s) in input with "CSS selector"
var stylesheet = {
"set" : {
"a" : {
"b" : [
{ "c" : "1" },
{ "c" : "2" }
]
}
},
"select" : ".a > .b .#c"
};
// output : [1, 2]
for syntax see JSONSelect and JSONSelect Expression Tester
Note:
select
always returns an array (an empty array when nothing was selected).
- module: basics
Convert input to specific type
var stylesheet1 = {
"set" : "1"
"cast": "number"
};
// output : 1
var stylesheet2 = {
"set" : 1
"cast": "string"
};
// output: "1"
for syntax see transtype
- module: basics
Selecting specific parts of input, hiding the rest, return object
var stylesheet = {
"set" : {
"a" : 1,
"b" : 2,
"c" : 3
},
"mask": "a,c"
};
// output : { a: 1, c: 3}
For syntax see json-mask
- module: basics
Unselecting specific parts of input, show the rest, return object
var stylesheet = {
"set" : {
"a" : 1,
"b" : 2,
"c" : 3
},
"omit": "a,c"
};
// output : { b: 2 }
For syntax see object.omit
- module: basics
If input is not set, return Error
- module: basics
Trim input, return string
var stylesheet = {
"set" : " xxx ",
"trim": true
};
// output : "xxx"
- module: basics
If expression is true, then statements will be continued, otherwise it is stopped and it returns null
Note :
this
variable contains input
var stylesheet1 = {
"set" : {
"a" : 1
},
"$val#1" : {
"assert": "a == 1",
"set" : "if val"
}
};
// output : "if val"
var stylesheet2 = {
"set" : {
"a" : 0
},
"$val#1" : {
"assert": "a == 1",
"set" : "if val"
},
"$val#2" : {
"get" : "val",
"default": "else val",
}
};
// output : "else val"
- module: ejs
Capitalize the first letter of input
var stylesheet = {
"set" : "xyz",
"capitalize": true
};
// output : "Xyz"
- module: ejs
Downcase input
var stylesheet = {
"set" : "XYZ",
"downcase": true
};
// output : "xyz"
- module: ejs
Uppercase input
var stylesheet = {
"set" : "xyz",
"upcase": true
};
// output : "XYZ"
- module: ejs
Convert the input string to something valid in an URI. See https://tools.ietf.org/html/rfc3986
{
"slug spaces": {
"input": "with space",
"stylesheet": {
"slug": true
},
"expected": "with-space"
},
"slug lowercase": {
"input": "IN UPPERCASE",
"stylesheet": {
"slug": true
},
"expected": "in-uppercase"
},
"slug diacritics": {
"input": "En français",
"stylesheet": {
"slug": true
},
"expected": "en-francais"
},
"slug diacritics #2": {
"input": "Le Cinquième Élément",
"stylesheet": {
"slug": true
},
"expected": "le-cinquieme-element"
},
"slug unicode": {
"input": "i ♥ unicode",
"stylesheet": {
"slug": true
},
"expected": "i-unicode"
}
}
- module: ejs
Get the first element of input
var stylesheet = {
"set" : ["a", "b", "c"],
"first": true
};
// output : "a"
- module: ejs
Get the last element of input
var stylesheet = {
"set" : ["a", "b", "c"],
"last": true
};
// output : "c"
- module: ejs
Sort input object or array.
var stylesheet = {
"set": ["b", "c", "a"],
"sort": true
};
// output : ["a", "b", "c"]
- module: ejs
- aliases : sort_by
Sort input object the given prop
ascending.
var stylesheet = {
"set": [
{ "name": "zert" },
{ "name": "abcd" }
],
"sortBy": "name"
};
// output : [{ "name": "abcd" }, { "name": "zert" }]
- module: ejs
- aliases : length
Get the size or the length of input
var stylesheet1 = {
"set" : "12345",
"size": true
};
var stylesheet2 = {
"set" : [1,2,3,4,5],
"size": true
};
// output : 5
- module: ejs
Add input and value
var stylesheet1 = {
"set" : [2, 4, 1, 7, 9, 3],
"max" : true
};
// output : 9
var stylesheet2 = {
"set" : {a: 9, b: 4, c: 3, d: 5},
"max" : true
};
// output : 9
- module: ejs
Subtract value from input
var stylesheet1 = {
"set" : [2, 4, 1, 7, 9, 3],
"min" : true
};
// output : 1
var stylesheet2 = {
"set" : {a: 9, b: 4, c: 3, d: 5},
"min" : true
};
// output : 3
- module: ejs
Add input and value
var stylesheet = {
"set" : 4,
"plus": 3
};
// output : 7
var stylesheet = {
"set" : 4,
"plus": [1,2,3]
};
// output : [5,6,7]
- module: ejs
Subtract value from input
var stylesheet = {
"set" : 4,
"minus": 3
};
// output : 1
var stylesheet = {
"set" : 4,
"minus": [1,2,3]
};
// output : [3,2,1]
- module: ejs
Multiply input by value"
var stylesheet = {
"set" : 5,
"times": 5
};
// output : 25
var stylesheet = {
"set" : 4,
"times": [1,2,3]
};
// output : [4,8,12]
- module: ejs
- aliases : divided_by
Divide input by value"
var stylesheet = {
"set" : 10,
"dividedBy": 2
};
// output : 5
var stylesheet = {
"set" : 4,
"times": [1,2]
};
// output : [4,2]
- module: ejs
- aliases : glue
Join input with the given string.
var stylesheet = {
"set" : ["a","b","c"],
"join": " | "
};
// output : "a | b | c"
- module: ejs
Shift input to the left by n
var stylesheet = {
"set" : "The world",
"shift": 4
};
// output : "world"
var stylesheet = {
"set" : [1,2,3,4,5],
"shift": 2
};
// output : [3,4,5]
var stylesheet = {
"set" : [1,2,3,4,5],
"shift": [2,3]
};
// output : [[3,4,5],[4,5]]
- module: ejs
Truncate input to length.
var stylesheet = {
"set" : "hello world",
"truncate": 5
};
// output : "hello"
- module: ejs
- aliases : truncate_words
Truncate input to n words (separator: space).
var stylesheet = {
"set" : "This is JBJ!",
"truncateWords": 2
}
// output "This is"
var stylesheet = {
"set" : "This is JBJ!",
"truncateWords": [1,2]
}
// output ["This","This is"]
- module: ejs
Replace pattern (as a regular expression) with substitution in input.
var stylesheet = {
"set" : "XoXoXoX",
"replace": ["o", "."]
};
// output : X.X.X.X
var stylesheet = {
"set" : "XoXoXoX",
"replace": "o"
};
// output : XXXX
Tip: to escape any character, use
\\
instead of just\
. Example: use"replace": "\\(trash\\)"
removes(trash)
from input, whereas"replace": "(trash)"
removes onlytrash
.
- module: ejs
Prepend something to input
var stylesheet = {
"set" : "world"
"prepend": "hello"
};
// output : "hello world"
var stylesheet = {
"set" : "h"
"prepend": ["a","e","i","o","u"]
};
// output : ["ah","eh","ih","oh","uh"]
- module: ejs
Append something to input
var stylesheet = {
"set" : "cool",
"append": "!"
};
// output : "cool!"
var stylesheet = {
"set" : "cool",
"append": ["!","?","."]
};
// output : ["cool!","cool?","cool."]
- module: ejs
Reverse items order of input
var stylesheet = {
"set" : [1,2,3]
};
// output : [3,2,1]
- module: ejs
Flatten an array.
var stylesheet = {
"set" : [ ['a', 'b'], ['c', 'd'], 'e'],
"flatten" : true
};
// output : ["a","b","c","d","e"]
- module: ejs
- aliases : dedupe , unique
Deduplicate values in an array.
var stylesheet = {
"set" : [ 1, 2, 3, 1, 2],
"deduplicate" : true
};
// output : [1,2,3]
- module: ejs
- alias : del
Remove one value in an array.
var stylesheet = {
"set" : [ 1, 2, 3],
"remove" : 2
};
// output : [1,3]
var stylesheet = {
"set" : [ "a", "", "b"],
"remove" : ""
};
// output : ["a","b"]
var stylesheet = {
"set" : [ "a", "b", "c"],
"remove" : "b"
};
// output : ["a","c"]
- module: ejs
- alias : total
Return the sum of all the value of an array.
var stylesheet = {
"set" : [ 1, 2, 3],
"sum" : true
};
// output : 6
just add #
var stylesheet = {
"default": "123456789",
"truncate#1": 8,
"truncate#2": 4,
"truncate#3": 2
};
just use this
var stylesheet = {
"$e" : {
"compute#1": "a / b",
"compute#2": "round(this)",
"cast": "number"
}
}
see unit tests : https://github.com/castorjs/node-jbj/tree/master/test