JBJ : transform Json By Json
A new way to transform JSON object with a JSON stylesheet. It's like XSL/XML but only with JSON.
Try it online !
http://inist-cnrs.github.io/jbj-playground/
Contributors
Installation
With npm do:
$ npm install jbj
Tests
Use mocha to run the tests.
$ npm install
$ npm test
Documentation
API
render(stylesheet : Object, input : Mixed, callback : Function) : None
Render input
with stylesheet
.
var JBJ = JBJ; // Output : 123
Variables
Variable can be set using $
plus a dot notation path.
The set value can only be a JBJ expression (not a JSON literal).
Input:
Stylesheet:
Output:
inject(stylesheet : Object, input : Mixed, callback : Function) : None
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 = JBJ; // Output : 123
prefix
var input = key : "hello"var stylesheet = "obj" : "<get" : "key" upcase: true ;// output : { obj : "HELLO" }
suffix
var input = key : "hello"var stylesheet = "obj" : "keyword<" : get : "key" upcase: true ;// output : { obj : { keyword : "HELLO" } }
register(protocol : String, callback : Function) : None
Add a function to fetch data for a specific protocol
JBJ;
getActions() : Array
List all available actions.
var JBJ = console; // Output : ['get', 'set', 'expect' ...]
getFilter(filterName : String) : Function
Get the statement function for an action name.
var JBJ = var func = JBJ; // Output : HelloWorld
use(module: Function) : None
Adding filters/actions for external module. see the avaible modules here : https://www.npmjs.com/browse/keyword/jbj
var JBJ = JBJ; JBJ; JBJ;
Warning: the method has change since v4.0
Actions
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;
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).
set: value
- module: basics
Set value and ignore input
var stylesheet1 = "set": "value" ; var stylesheet2 = "set": "value" "value" "value" ; var stylesheet3 = "set": "a": 1 "b": 2 ;
get: path | [path,path, ...]
- 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]
default: value
- module: basics
Fix value if input is not set
var stylesheet = var stylesheet = "default": "value" ; ;
fetch
- 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 "parseJSON" : true "path": "name" "$main": "fetch" : "file://" + path "parseJSON" : true "path": "main" ;
add: [key, value]
- module: basics
Add a key/value pair into the input object.
expect: object
- 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.
inject:
- module: basics
Return a new Object with JBJ.inject.
render:
- module: basics
Return a new Object with JBJ.render.
compute:
- 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
debug: none
- module: basics
Print input with console.log
var stylesheet = "set": "value" "debug": true ; // output: value
foreach: stylesheet
- 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" } ]
extend: object
- module: basics
- aliases : extendWith
Extend input with another object
var stylesheet = "set": "a" : 1 "extend" : "b" : 2 ; // output : { a: 1, b: 2}
select: path | [path, path, ...]
- 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).
cast: (number|string|boolean) | [(string|date), pattern]
- 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
mask: pattern
- 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
omit: pattern
- 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
required: none
- module: basics
If input is not set, return Error
trim: none
- module: basics
Trim input, return string
var stylesheet = "set" : " xxx " "trim": true ; // output : "xxx"
assert: expression
- 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"
capitalize:
- module: ejs
Capitalize the first letter of input
var stylesheet = "set" : "xyz" "capitalize": true ; // output : "Xyz"
downcase:
- module: ejs
Downcase input
var stylesheet = "set" : "XYZ" "downcase": true ; // output : "xyz"
upcase:
- module: ejs
Uppercase input
var stylesheet = "set" : "xyz" "upcase": true ; // output : "XYZ"
slug:
- 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"
first:
- module: ejs
Get the first element of input
var stylesheet = "set" : "a" "b" "c" "first": true ; // output : "a"
last:
- module: ejs
Get the last element of input
var stylesheet = "set" : "a" "b" "c" "last": true ; // output : "c"
sort:
- module: ejs
Sort input object or array.
var stylesheet = "set": "b" "c" "a" "sort": true ; // output : ["a", "b", "c"]
sortBy: prop | [prop, prop, ...]
- 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" }]
size:
- module: ejs
- aliases : length
Get the size or the length of input
var stylesheet1 = "set" : "12345" "size": true ; var stylesheet2 = "set" : 12345 "size": true ; // output : 5
max:
- 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
min:
- 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
plus: value | [value, value, ...]
- module: ejs
Add input and value
var stylesheet = "set" : 4 "plus": 3 ; // output : 7 var stylesheet = "set" : 4 "plus": 123 ; // output : [5,6,7]
minus: value | [value, value, ...]
- module: ejs
Subtract value from input
var stylesheet = "set" : 4 "minus": 3 ; // output : 1 var stylesheet = "set" : 4 "minus": 123 ; // output : [3,2,1]
times: value | [value, value, ...]
- module: ejs
Multiply input by value"
var stylesheet = "set" : 5 "times": 5 ; // output : 25 var stylesheet = "set" : 4 "times": 123 ; // output : [4,8,12]
dividedBy: value | [value, value, ...]
- module: ejs
- aliases : divided_by
Divide input by value"
var stylesheet = "set" : 10 "dividedBy": 2 ; // output : 5 var stylesheet = "set" : 4 "times": 12 ; // output : [4,2]
join: string = ', '
- module: ejs
- aliases : glue
Join input with the given string.
var stylesheet = "set" : "a""b""c" "join": " | " ; // output : "a | b | c"
shift: n | [n, n, ...]
- module: ejs
Shift input to the left by n
var stylesheet = "set" : "The world" "shift": 4 ; // output : "world" var stylesheet = "set" : 12345 "shift": 2 ; // output : [3,4,5] var stylesheet = "set" : 12345 "shift": 23 ; // output : [[3,4,5],[4,5]]
truncate: length | [length, length, ...]
- module: ejs
Truncate input to length.
var stylesheet = "set" : "hello world" "truncate": 5 ; // output : "hello"
truncateWords: n | [n, n, ...]
- 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": 12 // output ["This","This is"]
replace: [pattern, substitution] | pattern
- 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
.
prepend: something | [something, something, ...]
- 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"]
append: something | [something, something, ...]
- module: ejs
Append something to input
var stylesheet = "set" : "cool" "append": "!" ; // output : "cool!" var stylesheet = "set" : "cool" "append": "!""?""." ; // output : ["cool!","cool?","cool."]
reverse:
- module: ejs
Reverse items order of input
var stylesheet = "set" : 123 ; // output : [3,2,1]
flatten:
- module: ejs
Flatten an array.
var stylesheet = "set" : 'a' 'b' 'c' 'd' 'e' "flatten" : true ; // output : ["a","b","c","d","e"]
deduplicate:
- module: ejs
- aliases : dedupe , unique
Deduplicate values in an array.
var stylesheet = "set" : 1 2 3 1 2 "deduplicate" : true ; // output : [1,2,3]
remove:
- 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"]
sum:
- module: ejs
- alias : total
Return the sum of all the value of an array.
var stylesheet = "set" : 1 2 3 "sum" : true ; // output : 6
FAQ
How to chain the same action
just add #
var stylesheet = "default": "123456789" "truncate#1": 8 "truncate#2": 4 "truncate#3": 2 ;
How to use input as variable in an expression
just use this
var stylesheet = "$e" : "compute#1": "a / b" "compute#2": "round(this)" "cast": "number"
How to find more examples
see unit tests : https://github.com/castorjs/node-jbj/tree/master/test
Also
- http://goessner.net/articles/jsont/
- http://stedolan.github.io/jq/
- http://danski.github.io/spahql/
- https://github.com/MaxMotovilov/adstream-js-frameworks/wiki/Jxl-usage
- http://www.jsoniq.org/