如何使用jq遍历JSON规则并将数字引用替换为对应名称?
问题:将智能家居规则中的数字引用替换为对应名称
我通过单次API调用获取到了包含灯光、群组、规则、传感器的完整JSON数据(简化后如下):
{ "lights": { "8": { "name": "Room 1 Main" } }, "groups": { "1": { "name": "Room 1", "lights": [ "8", "9", "10", "11", "12" ] } }, "rules": { "1": { "name": "Light ON", "conditions": [{ "address": "/sensors/9/state/presence", "operator": "eq", "value": "true" }, { "address": "/sensors/10/state/lightlevel", "operator": "lt", "value": "12000" } ], "actions": [{ "address": "/lights/8/state", "method": "PUT", "body": { "on": true } }] } }, "sensors": { "9": { "name": "Room 1 Motion" }, "10": { "name": "Room 1 Lux" } } }
规则中的conditions和actions字段通过地址字符串引用了sensors、lights或groups的ID,我需要将这些数字ID替换为对应对象的name值,生成易读的规则格式,示例输出如下:
{ "name": "Light ON", "conditions": ["Room 1 Motion eq true", "Room 1 Lux lt 12000" ], "actions": "Room 1 Main on true" }
补充说明:动作的body字段可能包含on、flag(取值为true/false)或status(取值为enabled/disabled)。
请问如何遍历每个规则及其下的条件与动作,完成上述替换?
解决方案
核心思路
- 解析地址字符串:从
address中提取资源类型(如sensors、lights、groups)和对应的ID; - 建立名称映射:利用API返回的
sensors、lights、groups数据,创建ID到名称的映射表; - 遍历处理规则:逐个处理每个规则的条件和动作,替换ID为名称并格式化字符串。
代码实现示例(JavaScript)
// 假设apiData是API返回的完整JSON数据 const apiData = { /* 你的API返回数据 */ }; // 构建ID到名称的映射表 const nameMap = { sensors: Object.fromEntries(Object.entries(apiData.sensors).map(([id, item]) => [id, item.name])), lights: Object.fromEntries(Object.entries(apiData.lights).map(([id, item]) => [id, item.name])), groups: Object.fromEntries(Object.entries(apiData.groups).map(([id, item]) => [id, item.name])) }; // 从地址中解析对应资源的名称 function getNameFromAddress(address) { const parts = address.split('/'); const type = parts[1]; const id = parts[2]; // 容错:如果找不到对应名称,返回标识文本 return nameMap[type]?.[id] || `Unknown ${type} ${id}`; } // 处理单个规则 function processRule(rule) { // 格式化条件数组 const conditions = rule.conditions.map(cond => { const resourceName = getNameFromAddress(cond.address); return `${resourceName} ${cond.operator} ${cond.value}`; }); // 格式化动作(支持多个动作拼接) const actions = rule.actions.map(action => { const resourceName = getNameFromAddress(action.address); // 提取body中的配置项(适配on/flag/status) const [configKey, configValue] = Object.entries(action.body)[0]; return `${resourceName} ${configKey} ${configValue}`; }).join(', '); return { name: rule.name.trim(), conditions, actions }; } // 批量处理所有规则 const processedRules = Object.values(apiData.rules).map(processRule); // 输出结果 console.log(JSON.stringify(processedRules, null, 2));
关键细节说明
- 地址解析:通过
split('/')拆分地址字符串,稳定提取资源类型和ID,适配三种资源类型; - 映射表优化:用
Object.fromEntries快速转换原数据结构,后续查询名称的时间复杂度为O(1); - 动作适配:通过
Object.entries动态获取body中的配置项,无需硬编码判断on/flag/status; - 容错处理:遇到未知资源或ID时返回标识文本,避免程序中断。
内容的提问来源于stack exchange,提问作者Lorccan
相关产品推荐
相关产品推荐

