I want to remove the inner keywords attributes and elements such that the attributes and elements are part of the json object itself. Is there a way in doing this in Rascal for a json file.
{
"attributes": {
"name": "\"physics\""
},
"elements": {
"material": [
{
"attributes": {
"name": "\"blue\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
-1.2,
0,
0.8,
1
]
}
}
]
}
},
{
"attributes": {
"name": "\"black\""
},
"elements": {
"color": [
{
"attributes": {
"rgba": [
0,
0,
0,
1
]
}
}
]
}
}
],
}
}
I created a data structure that parses key value pairs of a xml file. In the json file I want to get rid of the attributes and elements and use nested objects instead of elements.
In javascript I got this to work.
function collapse(e){
let elements = {};
for(const key in e.elements){
for(const element of e.elements[key]){
elements[key] = collapse(element)
}
}
return {...e.attributes, ...elements}
}
This answer is a very specific transformation that is only relevant for your particular choice of JSON objects which have "attributes" and "elements" fields for every object. It is a bit puzzling why we have this "double encoding" of objects in the first place, but nevertheless you can remove it with Rascal.
This is a bottom-up transformation that matches the structure of every node and transforms it to another using functions from the Node
module in the standard library. We need this to be able to create nodes of arbitrary arities, for which there is no syntax yet.
import Map;
import Node;
// the heavy work is the pattern match that uses the contract of the
// encoding: two attributes named "attributes" and "elements", each pointing to another object that encodes a map.
value transform("object"(attributes=node attrs, elements=node elems))
= makeNode([transform(x) | value x <- getKeywordParameters(elems)<1>],
keywordParameters=(k:transform(b) | <k,v> <- toRel(getKeywordParameters(attrs));
// lists need some recursion
value transform(list[value] l) = [transform(e) | e <- l];
// all other stuff is copied one-to-one
default value transform(value v) = v;
I did not test this yet, but you get a general idea. Recursion + pattern based dispatch for each case.