如何自底向上遍历深度嵌套JSON并清理空字段?
问题
需要高效自底向上遍历深度嵌套的JSON,移除所有空字段、值为'-'或'none'的字段。当前自上而下的遍历只能移除最底层的空字段,无法把清空后变成空对象的父字段(比如示例中的tls)也一并移除。
数据示例
{ "rule": { "description": "authentication_failed", "category": { "action": "denied" } }, "tls": { "client": { "certificate": { "subject": "-" } }, "server": { "certificate": { "subject": "-" } } } }
当前使用代码
def removeEmptyFields(event,h,name) h.each do |k,v| if (v.is_a?(Hash) || v.is_a?(Array)) && v.to_s != '{}' removeEmptyFields(event,v,String.new(name.to_s) << '[' << k.to_s << ']') else if v == '' || v == '-' || v == 'none' || v.to_s == '{}' event.remove(String.new(name.to_s) << '[' << k.to_s << ']') end end end end removeEmptyFields event,event.to_hash,''
当前输出
{ "rule": { "description": "authentication_failed", "category": { "action": "denied" } }, "tls": { "client": { "certificate": {} }, "server": { "certificate": {} } } }
期望结果
tls字段被整体移除,因为其下所有子字段清理后,tls本身变为空对象。
解决方案
核心问题是原代码采用自上而下遍历,先处理父节点再处理子节点,子节点清空后父节点已经处理完毕,无法回头判断是否需要删除。正确思路是自底向上遍历:先处理所有子节点,再检查父节点是否因子节点清空而变成空对象,进而移除。
以下是修改后的Ruby代码,直接操作哈希对象实现自底向上清理:
def clean_hash(hash) # 先递归清理所有子哈希和数组 hash.each do |k, v| case v when Hash clean_hash(v) # 子哈希清理后为空则删除当前键 hash.delete(k) if v.empty? when Array # 先清理数组里的哈希元素 v.each { |item| clean_hash(item) if item.is_a?(Hash) } # 过滤掉需要移除的元素,空数组也一并删除 hash[k] = v.reject { |item| item == '' || item == '-' || item == 'none' || (item.is_a?(Hash) && item.empty?) } hash.delete(k) if hash[k].empty? else # 直接移除符合条件的叶子节点 hash.delete(k) if v == '' || v == '-' || v == 'none' end end hash end # 使用示例:假设event是解析后的JSON哈希 cleaned_event = clean_hash(event.to_hash) # 如需转回JSON对象,可根据使用的库处理,比如: # cleaned_json = JSON.generate(cleaned_event)
代码说明
- 自底向上逻辑:先递归处理所有子节点,子节点清理完成后再判断当前节点是否需要删除。
- 哈希处理:子哈希清理后为空,直接删除对应的父键。
- 数组处理:先清理数组内的哈希元素,再过滤掉符合移除条件的元素,空数组也会被删除。
- 叶子节点判断:直接移除值为
''、'-'、'none'的字段。
用这段代码处理示例数据,会得到期望结果:
{ "rule": { "description": "authentication_failed", "category": { "action": "denied" } } }
内容的提问来源于stack exchange,提问作者starrywrites
相关产品推荐
相关产品推荐

