Select a JSON object or its subtree that matches your filter function
Step 1. Take any JSON object
var data = {
"links": [
{ "remote_url": "http://localhost" },
{ "file_url": "file://documents" },
{ "remote_url": "https://blahblah.com" }
],
"preview": "https://image",
"metadata": "This is a link collection"
}
Step 2. Find all key/value pairs that match a selector function
var sel = ST.select(data, function(key, val) {
return /https?:/.test(val);
})
Step 3. Once selected, you can make queries.
var keys = sel.keys();
// [
// "remote_url",
// "remote_url",
// "preview"
// ]
var values = sel.values();
// [
// "http://localhost",
// "https://blahblah.com",
// "https://image"
// ]
var paths = sel.paths();
// [
// "[\"links\"]",
// "[\"links\"]",
// ""
// ]
Transform any JSON with a declarative template, also in JSON.
Step 1. Take any JSON object
var data = {
"title": "List of websites",
"description": "This is a list of popular websites"
"data": {
"sites": [{
"name": "Google",
"url": "https://google.com"
}, {
"name": "Facebook",
"url": "https://facebook.com"
}, {
"name": "Twitter",
"url": "https://twitter.com"
}, {
"name": "Github",
"url": "https://github.com"
}]
}
}
Step 2. Select and transform with a template JSON object
var sel = ST.select(data, function(key, val){
return key === 'sites';
})
.transformWith({
"items": {
"{{#each sites}}": {
"tag": "<a href='{{url}}'>{{name}}</a>"
}
}
})
Step 3. Get the result
var keys = sel.keys();
// [
// "tag",
// "tag",
// "tag",
// "tag"
// ]
var values = sel.values();
// [
// "<a href='https://google.com'>Google</a>",
// "<a href='https://facebook.com'>Facebook</a>",
// "<a href='https://twitter.com'>Twitter</a>",
// "<a href='https://github.com'>Github</a>"
// ]
var objects = sel.objects();
// [
// {
// "tag": "<a href='https://google.com'>Google</a>"
// }, {
// "tag": "<a href='https://facebook.com'>Facebook</a>"
// }, {
// "tag": "<a href='https://twitter.com'>Twitter</a>"
// }, {
// "tag": "<a href='https://github.com'>Github</a>"
// }
// ]
var root = sel.root();
// {
// "items": [{
// "tag": "<a href='https://google.com'>Google</a>"
// }, {
// "tag": "<a href='https://facebook.com'>Facebook</a>"
// }, {
// "tag": "<a href='https://twitter.com'>Twitter</a>"
// }, {
// "tag": "<a href='https://github.com'>Github</a>"
// }]
// }
st.js
is a library that adds a couple of powerful methods to JavaScript's native JSON.ST.select(...).transform(...)
stateless functions
, with NO dependency
.embed anywhere
without hassle. (Currently used in various environments including iOS, Android, node.js, browser, etc.)Old way: Manually construct object
// app.js
app.get('/', function (req, res) {
var response = {}
response["current_user"] = {
username: "@" + req.user.username,
firstname: req.user.name.split(' ')[0],
lastname: req.user.name.split(' ')[1]
}
var transformed_posts = db.posts.map(function(post){
return {
slug: post.slug
permalink: "https://blahblahblah.blahblah/" + post.slug,
post_title: post.title,
post_content: post.content
}
})
response["posts"] = transformed_posts
res.json(response)
})
New way: Declarative approach with st.js
// app.js
app.get('/', function (req, res) {
res.json(ST.select(require('./template.json'))
.transform({user: req.user, posts: db.posts})
.root())
})
// template.json
{
"current_user": {
"username": "@{{user.username}}",
"firstname": "{{user.name.split(' ')[0]}}",
"lastname": "{{user.name.split(' ')[1]}}"
},
"posts": {
"{{#each posts}}": {
"slug": "{{slug}}",
"permalink": "https://blahblahblah.blahblah/{{slug}}",
"post_title": "{{title}}",
"post_content": "{{content}}"
}
}
}
JSON.stringify
or JSON.parse
Browser
var rpc = {
name: "add",
args: [2,3,1]
}
fetch("http://localhost:3000", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(rpc)
).then(function(res) {
console.log(res.json());
})
Server
// router.json
[{
"{{#if 'name' in this}}": [{
"{{#if name === 'add'}}": 'add_service'
}, {
"{{#elseif name === 'subtract'}}": [{
"{{#if args.length === 2}}": 'subtract_service'
}, {
"{{#else}}": 'error_service'
}]
}]
}, {
"{{#else}}": 'error_service'
}]
// express server
app.post('/', (req, res) => {
const Services = {
add_service: function(){
return Array.prototype.slice
.call(arguments)
.reduce((a,b) => {
return a+b;
}, 0)
},
subtract_service: function() {
return arguments[0] - arguments[1]
},
error_service: function() {
return 'error';
}
}
const name = ST.transform(require('./router.json'), req.body);
res.json(Services[name].apply(this, req.body.args));
});
router.json
), we don't even need it on the server side.router.json
on the server, but send it from the browser?Browser
var router = [{
"{{#if 'name' in this}}": [{
"{{#if name === 'add'}}": 'add_service'
}, {
"{{#elseif name === 'subtract'}}": [{
"{{#if args.length === 2}}": 'subtract_service'
}, {
"{{#else}}": 'error_service'
}]
}]
}, {
"{{#else}}": 'error_service'
}];
var rpc = {
name: "add",
args: [2,3,1],
router: router
}
fetch("http://localhost:3000", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(rpc)
).then(function(res) {
console.log(res.json());
})
Server
// express server
app.post('/', (req, res) => {
const Services = {
add_service: function(){
return Array.prototype.slice
.call(arguments)
.reduce((a,b) => {
return a+b;
}, 0)
},
subtract_service: function() {
return arguments[0] - arguments[1]
},
error_service: function() {
return 'error';
}
}
const name = ST.transform(req.body.router, req.body);
res.json(Services[name].apply(this, req.body.args));
});
st.js
is the core JSON parser that powers Jasonette, a framework that lets you build native iOS/Android apps by writing nothing but a JSON markup.<script src="st.js"></script>
<script>
var parsed = ST.select({ "items": [1,2,3,4] })
.transformWith({
"{{#each items}}": {
"type": "label", "text": "{{this}}"
}
})
.root();
</script>
Install through npm:
$ npm install stjs
Use
const ST = require('st');
const parsed = ST.select({ "items": [1,2,3,4] })
.transformWith({
"{{#each items}}": {
"type": "label", "text": "{{this}}"
}
})
.root();