JavaScript如何根据传入数据更新三层嵌套对象的值?
智能家居设备状态更新问题解决
问题背景
现有如下设备状态对象:
{ "room_1": { "fan": "on", "fan_state": 0, "light1": "on", "light2": "on", "light3": "off", "light4": "on" }, "room_2": { "fan": "on", "fan_state": 2, "light1": "off", "light2": "on", "light3": "on", "light4": "off" }, "room_3": { "fan": "on", "fan_state": 2, "light1": "off", "light2": "on", "light3": "on", "light4": "off" }, "room_4": { "fan": "on", "fan_state": 3, "light1": "off", "light2": "off", "light3": "off", "light4": "on" } }
需要根据传入的JSON字符串格式数据更新该对象,比如传入数据:
{"room_1":{"light1":"off"}}
但原有代码无法完成更新,以下是失败的代码:
var jsonRequest=flow.get('post_msg') || {}; var jsonObj = JSON.parse(jsonRequest); //var jsonObj = jsonRequest; var js_keys = Object.keys(jsonObj); //node.warn(jsonRequest); node.warn("jsonObj " + jsonObj + " and " + Object.keys(jsonObj) + " type " + typeof (jsonObj)); var oldJSON= msg.payload; var newJSON = oldJSON; node.error("1 oldJSON_ payload_newjson " + JSON.stringify(oldJSON) ); for (var key in newJSON){ node.error("for ok: " + key + " " + JSON.stringify(jsonObj[key]) + "" + JSON.stringify(newJSON[key]) + " io " + Object.keys(JSON.parse(jsonObj)) + " val " + JSON.stringify(Object.values(JSON.parse(jsonObj)) ) ); if (key == Object.keys(jsonObj)+"" ){ node.warn("true"); } node.error("1ppp " + JSON.stringify(newJSON[key]) ); for (var key2 in newJSON[key]){ node.error("2ppp " + jsonObj + " ok " + JSON.stringify(newJSON[key] )); //if (key2 == Object.keys(JSON.parse(jsonObj) ) ) { // newJSON[key][key2] = JSON.parse(jsonObj[key][key2]); //} } //} } //newJSON.room_1.light1 ="off" ; msg.payload=newJSON ; var msg_keys = Object.keys(jsonObj); node.error(msg_keys); msg.room_no = msg_keys.toString(); msg.inputs =jsonRequest; //msg.flags= oldJSON.flags; return msg;
问题代码分析
- 无效的键匹配逻辑:
key == Object.keys(jsonObj)+""会将数组转为逗号分隔的字符串,仅当更新数据只有一个键时可能偶然匹配,逻辑本质错误,且遍历原始对象所有房间完全没必要。 - 重复解析错误:多次执行
JSON.parse(jsonObj),但jsonObj已经是解析后的对象,重复解析会抛出异常。 - 冗余循环:遍历原始对象的所有房间和设备,没有针对性地处理更新数据中的目标键。
修复后的代码
// 获取传入的更新请求字符串 var jsonRequest = flow.get('post_msg') || '{}'; // 解析为JSON对象 var updateData = JSON.parse(jsonRequest); // 获取原始设备状态对象 var deviceState = msg.payload; // 遍历更新数据中的每个房间 for (const roomKey in updateData) { // 检查原始对象中是否存在该房间,避免无意义操作 if (deviceState[roomKey]) { // 遍历该房间内需要更新的设备 for (const deviceKey in updateData[roomKey]) { // 直接更新对应设备状态 deviceState[roomKey][deviceKey] = updateData[roomKey][deviceKey]; } } } // 设置返回的设备状态 msg.payload = deviceState; // 记录更新的房间号和原始请求内容 msg.room_no = Object.keys(updateData).toString(); msg.inputs = jsonRequest; return msg;
关键说明
- 精准遍历:仅遍历更新数据中的房间和设备,避免无意义的循环,提升执行效率。
- 避免重复解析:仅对传入的字符串执行一次
JSON.parse,后续直接操作对象,避免异常。 - 安全检查:先判断原始对象中是否存在目标房间,避免因更新数据包含不存在的房间导致错误。
内容的提问来源于stack exchange,提问作者Shariq Azim
相关产品推荐
相关产品推荐

