如何在JSLT中通过另一JSON对象的键获取对应值?
JSLT递归比较JSON对象并提取差异的解决方案
问题背景
需要用JSLT编写通用脚本,递归对比两个JSON对象(支持多层嵌套的对象和数组),仅保留差异元素。当前卡在通过一个对象的键动态获取另一个对象对应值的环节,示例输入JSON如下:
{ "itemOne": { "name": "Ralph" }, "itemTwo": { "name": "Steve" } }
尝试了多种写法均未达到预期:
- 写法一:
$itemOne.value返回null,因为它是在itemOne中查找名为value的键,而非使用循环的.key动态取值let itemOne = .itemOne { for(.itemTwo) .key : $itemOne.value } - 写法二:直接返回
itemOne全部内容,未提取对应键的值let itemOne = .itemOne { for(.itemTwo) .key : $itemOne } - 写法三:仅做字符串拼接,未实际取值
let itemOne = .itemOne { for(.itemTwo) let itemOneName = "$itemOne" + .key let fixed = "" .key : $itemOneName } - 写法四:抛出解析错误,语法使用错误
let itemOne = .itemOne { for(.itemTwo) .key : $itemOne(.value) }
解决方案
1. 单层级动态键值匹配
JSLT中通过动态键名取值需使用方括号语法,这是根据循环的.key值从目标对象中获取对应值的正确方式:
let itemOne = .itemOne { for(.itemTwo) .key : $itemOne[.key] }
对示例JSON运行后返回:
{"name": "Ralph"}
2. 递归对比通用脚本
以下脚本支持递归处理多层嵌套的对象和数组,仅保留两个对象的差异内容:
// 递归对比函数:返回两个节点的差异,无差异则返回null def diff(a, b) if (type($a) != type($b)) { // 类型不同,保留b的内容 $b } else if (type($a) == "object") { // 处理对象:遍历所有键对比值 { // 处理a有、b也有的键 for ($a) let b_val = $b[.key] if ($b_val == null) { .key : .value } else { let diff_val = diff(.value, $b_val) if ($diff_val != null) { .key : $diff_val } } // 补充b有、a没有的键 for ($b) if ($a[.key] == null) { .key : .value } } } else if (type($a) == "array") { // 处理数组:按索引对比(假设数组有序) [ // 对比a、b共有的元素 for (range(0, size($a)-1)) let diff_val = diff($a[.], $b[.]) if ($diff_val != null) { $diff_val } // 补充b中多出的元素 for (range(size($a), size($b)-1)) $b[.] ] } else { // 基础类型:值不同则返回b,相同则返回null if ($a != $b) $b else null } // 调用函数对比itemOne和itemTwo diff(.itemOne, .itemTwo)
对示例JSON运行后返回差异内容:
{"name": "Steve"}
如果是多层嵌套场景,比如:
{ "itemOne": { "name": "Ralph", "info": { "age": 30, "hobbies": ["reading", "hiking"] } }, "itemTwo": { "name": "Steve", "info": { "age": 35, "hobbies": ["reading", "running"] } } }
脚本会返回:
{ "name": "Steve", "info": { "age": 35, "hobbies": ["running"] } }
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

