JSON Template in Lua - json

I have a JSON object which I would like to templatize in lua. For example:
{
"type":"email",
"version":"1.0",
"account":"%emailId%"
}
I would like to substitute the %emailId% with a list of e-mail ids. Is there a templatization support for JSON in lua?

No, there is no built-in support for either JSON or templating in the core Lua language or libraries. There are a number of JSON modules available, but I'm not sure whether any of them have template support. You might have to write a templating function yourself, but it probably won't be too hard - it's just a matter of iterating over all the string values with the JSON module and using string.gsub on them.

Though it isn't intended for JSON you can use lua-resty-template.
user.json:
{ "user": "{{username}}" }
lua-code:
local template = require "resty.template"
local result = template.compile("user.json")({ username = "someone" })
print(result);
result:
{ "user": "someone" }

Related

What is the ideal way to JSON.stringify in Terraform?

I'm working on my first Terraform project and I'm looking for the best way to stringify a JSON object. The resource I'm defining has a parameter that expects a JSON string. JSON structure is:
"document": {
"tag": "String Title",
"response": "There's a string response and perhaps a price like $[XX.XX]."
}
}
I don't think jsonencode or jsondecode do this. I could stringify them in advance but that isn't scalable in this case. I wasn't sure if I could do this with JavaScript or another language alongside Terraform, or if there's a function in HCL that will do it.
jsonencode in Terraform is exactly equivalent to JSON.stringify with only one argument in JavaScript.
For example, if you need to assign a string containing a JSON object to an argument called something_json, you could do that like this:
something_json = jsonencode({
document = {
tag = "String Title"
response = "There's a string response and perhaps a price like $[XX.XX]."
}
})
The above would set something_json to a minified version of the following JSON:
{
"document": {
"tag": "String Title",
"response": "There's a string response and perhaps a price like $[XX.XX]."
}
}
Terraform does not have an equivalent of the optional replacer and space arguments in JavaScript's JSON.stringify:
An equivalent of replacer isn't needed in Terraform because all possible values in the Terraform language have a defined JSON equivalent as described in the table in the jsonencode documentation.
space is for generating non-minified JSON; Terraform does not offer any way to do this because it is focused on generating JSON for machine consumption and so prefers to generate the most compact representation possible.

How do I programmatically create JSON in XQuery in MarkLogic?

I need to build up a JSON node in XQuery in MarkLogic. I know that I can use xdmp:unquote() to parse from a string into a node(). However, I’d like to build the JSON programmatically, without ugly string concatenation. I can use computed element constructors to build XML nodes in XQuery. Is there something similar for JSON nodes?
JSON is implemented in MarkLogic as an extension to the XML data model. MarkLogic 8 introduces object-node, array-node, number-node, boolean-node, and null-node tests and constructors. Thus, in XQuery you can build JSON with computed constructors, just like you would with XML. For example,
object-node {
"key" || fn:string(xdmp:random(100)): array-node { 1, 2, 3 },
"another": object-node { "child": text {'asdf'} },
"lastButNotLeast": boolean-node { fn:true() }
}
will create the JSON,
{
"key47": [1, 2, 3],
"another": {
"child": "asdf"
},
"lastButNotLeast": true
}
Aside: In JavaScript you can build JSON-like structures as JavaScript objects using JavaScript syntax. You can convert a JavaScript object into a JSON node using xdmp.toJSON(). Most builtin functions that require a JSON node, however, will do this conversion automatically, such as xdmp.documentInsert().

Standardized way to serialize JSON to query string?

I'm trying to build a restful API and I'm struggling on how to serialize JSON data to a HTTP query string.
There are a number of mandatory and optional arguments that need to be passed in the request, e.g (represented as a JSON object below):
{
"-columns" : [
"name",
"column"
],
"-where" : {
"-or" : {
"customer_id" : 1,
"services" : "schedule"
}
},
"-limit" : 5,
"return" : "table"
}
I need to support a various number of different clients so I'm looking for a standardized way to convert this json object to a query string. Is there one, and how does it look?
Another alternative is to allow users to just pass along the json object in a message body, but I read that I should avoid it (HTTP GET with request body).
Any thoughts?
Edit for clarification:
Listing how some different languages encodes the given json object above:
jQuery using $.param: -columns[]=name&-columns[]=column&-where[-or][customer_id]=1&-where[-or][services]=schedule&-limit=5&return=column
PHP using http_build_query: -columns[0]=name&-columns[1]=column&-where[-or][customer_id]=1&-where[-or][services]=schedule&-limit=5&return=column
Perl using URI::query_form: -columns=name&-columns=column&-where=HASH(0x59d6eb8)&-limit=5&return=column
Perl using complex_to_query: -columns:0=name&-columns:1=column&-limit=5&-where.-or.customer_id=1&-where.-or.services=schedule&return=column
jQuery and PHP is very similar. Perl using complex_to_query is also pretty similar to them. But none look exactly the same.
URL-encode (https://en.wikipedia.org/wiki/Percent-encoding) your JSON text and put it into a single query string parameter. for example, if you want to pass {"val": 1}:
mysite.com/path?json=%7B%22val%22%3A%201%7D
Note that if your JSON gets too long then you will run into a URL length limitation problem. In which case I would use POST with a body (yes, I know, sending a POST when you want to fetch something is not "pure" and does not fit well into the REST paradigm, but neither is your domain specific JSON-based query language).
There is no single standard for JSON to query string serialization, so I made a comparison of some JSON serializers and the results are as follows:
JSON: {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"logankeller#artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"}
Rison: (_id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller#artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258')
O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller#artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258'
JSURL: ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana)
QS: _id=5973782bdb9a930533b05cb2&isActive=true&balance=$1,446.35&age=32&name=Logan Keller&email=logankeller#artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana
URLON: $_id=5973782bdb9a930533b05cb2&isActive:true&balance=$1,446.35&age:32&name=Logan%20Keller&email=logankeller#artiq.com&phone=+1%20(952)%20533-2258&friends#$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana
QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana
The shortest among them is URL Object Notation.
How about you try this sending them as follows:
http://example.com/api/wtf?
[-columns][]=name&
[-columns][]=column&
[-where][-or][customer_id]=1&
[-where][-or][services]=schedule&
[-limit]=5&
[return]=table&
I tried with a REST Client
And on the server side (Ruby with Sinatra) I checked the params, it gives me exactly what you want. :-)
Another option might be node-querystring. It also uses a similar scheme to the ones you've so far listed.
It's available in both npm and bower, which is why I have been using it.
Works well for nested objects.
Passing complex objects as query parameters of a url.
In the example below, obj is the JSON object to pass into query parameters.
Injecting JSON object as query parameters:
value = JSON.stringify(obj);
URLSearchParams to convert a string to an object representing search params. toString to retain string type for appending to url:
queryParams = new URLSearchParams(value).toString();
Pass the query parameters using template literals:
url = `https://some-url.com?key=${queryParams}`;
Now url will contain the JSON object as query parameters under key (user-defined name)
Extracing JSON from url:
This is assuming you have access to the url (either as string or URL object)
url_obj = new URL(url); (only if url is NOT a URL object, otherwise ignore this step)
Extract all query parameters in the url:
queryParams = new URLSearchParams(url_obj.search);
Use the key to extract the specific value:
obj = JSON.parse(queryParams.get('key').slice(0, -1));
slice() is used to extract a tailing = in the query params which is not required.
Here obj will be the same object passed in the query params.
I recommend to try these steps in the web console to understand better.
You can test with JSON examples here: https://json.org/example.html

How to avoid quotes when encoding a JSON object

I need to create something like the following JSON entity:
{
"foo": function() { *some code* }
}
Can any of the common JSON libraries (json, jsonb, aeron etc.) easily achieve that?
I didn't find a way to tell the library not to quote the function part when encoding.
Thanks,
p.s. I understand the reason for not allowing such usage is to enforce correct syntax, but I'm willing to take that risk here.
That is not a JSON entity, but a JavaScript object. JSON has no concept of functions.
The only way to have a function encoded in JSON is indeed to encode it in a string:
{ "foo": "function() { return \"Hello, World\" }" }
When you want to execute that function in JavaScript, you'll have to eval the string:
var jsonObj = JSON.parse('{ "foo": "function() {return \\"Hello, World\\";}" }');
var jfoo = eval('(' + jsonObj.foo + ')');
alert(jfoo()); // Shows a dialog box "Hello, World"
Note that this allows the source of the JSON to execute arbitrary JavaScript in the context of your website or application. Therefore, you should transfer data instead of functions whenever possible, and make sure not to eval code from untrusted sources.

Parsing JSON with Erlang (erlang-rfc4627 lib)

I am attempting to get some JSON parsed with erlang-rfc4627 and struggling with the returned results
This is the JSON:
{
"people": [
{"name": "Toby"}
]
}
Using the erlang-rfc4627 library:
{ok, Json, []} = rfc4627:decode("...")
I can decode fine into Erlang as:
{obj,[
{"people",[
{obj,[
{"name",<<"Toby">>}
]},
{obj,[
{"name",<<"Blah">>}
]}
]}
]}
But then what happens?
How do I get an array of people out of this structure in an easy way?
(This is a very simplified model of the overall JSON).
Is there a better library I should be using for this?
Updated
I noticed that when pulling out arrays, each element of the arrays has the awful obj structure wrapped into it, which makes the process of manipulating arrays very clumsy.
Why on earth is this so complex in Erlang?
Reference: http://www.lshift.net/blog/2007/02/17/json-and-json-rpc-for-erlang
How about:
lookup(K, {obj, PL}) -> proplists:get_value(K, PL).
And then
People = lookup("people", JSON),
Names = [lookup("name", Obj) || Obj <- People].
The better way generalizes this idea into a query-compiler which can compile any query to a function which can then be applied to a JSON document. It will be way easier should you want to to rumaging inside JSON documents all the time.
It is also important to note that you should probably not be operating directly on the JSON structure, but embed it in something else inside the Erlang world.
Is there a better library I should be using for this?
Please, try use library like jiffy, because this library is easy to use:
1> Doc = {[{foo, [<<"bing">>, 2.3, true]}]}.
{[{foo,[<<"bing">>,2.3,true]}]}
2> BinJSON = jiffy:encode(Doc).
<<"{\"foo\":[\"bing\",2.3,true]}">>
3> JsonMap = jiffy:decode(BinJSON, [return_maps]).
#{<<"foo">> => [<<"bing">>,2.3,true]}
4> maps:get(<<"foo">>, JsonMap, undefined).
[<<"bing">>,2.3,true]