如何在Rascal中移除JSON的attributes与elements嵌套并整合结构?
问题描述
我解析XML键值对生成的JSON结构里,存在attributes和elements两层嵌套,现在需要移除这两个关键字,把它们包含的内容直接整合到对应JSON对象中,用嵌套对象替代原elements的结构。我已经用JavaScript实现了这个逻辑(代码如下),现在需要用Rascal完成同样的操作。
示例输入JSON
{ "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 ] } } ] } } ], }}
JavaScript实现代码
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} }
Rascal实现方案
在Rascal中可以利用递归函数结合JSON模块的模式匹配来实现相同逻辑,代码如下:
import JSON; // 递归折叠JSON结构,移除attributes和elements嵌套 value collapse(value node) { // 处理同时包含attributes和elements的节点 if (node matches obj("attributes": attr, "elements": elems)) { value processedElements = obj(); // 遍历elements中的每个键值对 for (str key <- keys(elems), value elemArray <- elems[key]) { // 遍历数组内的元素,递归折叠后覆盖赋值(与JS逻辑保持一致) for (value elem <- elemArray) { processedElements[key] = collapse(elem); } } // 合并attributes和处理后的elements对象 return merge(attr, processedElements); } // 处理仅包含attributes的节点 else if (node matches obj("attributes": attr)) { return attr; } // 其他类型(如数组、基础值)直接返回 return node; }
逻辑说明
- 模式匹配:通过
matches关键字匹配包含attributes和elements的JSON对象,分别提取属性和子元素。 - 递归处理:对
elements中每个键对应的数组元素递归调用collapse,完成嵌套结构的扁平化。 - 对象合并:使用
merge函数将attributes的内容与处理后的子元素对象合并,得到最终的扁平化结构。 - 边界处理:针对仅包含
attributes的节点直接返回属性内容,其他类型(如数组、数值等)原样返回。
内容的提问来源于stack exchange,提问作者Twan Bolwerk
相关产品推荐
相关产品推荐

