返回嵌套JSON中包含特定键的所有值

Returning all values that contain a particular key in nested JSON?

本文关键字:嵌套 JSON 包含特 返回      更新时间:2023-09-26

我嵌套了如下JSON:

{
    "fields": {
        "type": "custom",
        "level1": {
            "type": "custom"
        },
        "level2": {
            "type": "custom",
            "level3": {
                "type": "custom"
            },
            "level31": {
                "type": "notcustom"
            }
        }
    }
}

我想提取所有具有密钥type 的值

我想要的输出是:

{
    "fields":"custom",
    "level1":"custom",
    "level2":"custom"
}

我试图使用递归方法变得简单。首先检查它是否为对象。如果它是一个对象,则再次调用传递该对象的函数。

否则,请检查该键和相应的值是否存在。在结果对象中填充并返回。

    var object = {
      "fields": {
        "type": "custom",
        "level1": {
          "type": "custom"
        },
        "level2": {
          "type": "custom",
          "level3": {
            "type": "custom"
          },
          "level31": {
            "type": "notcustom"
          }
        }
      }
    };
    function recursiveIterator(object, needle, value, result) {
      var result = result || {};
      for (var key in object) {
        if (object[key][needle] === value) {
          result[key] = object[key][needle];
        }
        if (typeof object[key] === "object") {
          recursiveIterator(object[key], needle, value, result);
        }
      }
      return result;
    }
    document.getElementById("result").textContent = JSON.stringify(recursiveIterator(object, "type", "custom"));
<div id="result"></div>

这是一种非常通用的方法。在这种情况下,您可以传递key(如type),以及您想要匹配的值(在这种情况中为custom)。

您需要一个递归函数来导航树结构。

下面的代码片段实现了这一点,并将结果添加到一个自定义字段数组中。

我没有删除自定义字段的子属性,所以如果自定义字段具有子级别属性,则该属性也包含在内。您可以删除这些子属性,但也可以修改源对象树。因此,这可以解决用Object.create创建克隆并随后删除整个属性的问题。。。但我相信,整个代码足以让你敞开心扉,了解如何解决这个问题。

运行代码段以实时查看JSON结果!

更新

尽管您请求了一个对象作为结果(毕竟有点像字典),但我建议数组结果在这种情况下应该更好地工作,因为如果有多个"级别"属性以相同的方式调用(例如,两个level1属性),则结果中只有最后一个可以访问,因为它可能会被覆盖

var obj = {
    "fields": {
        "type": "custom",
            "level1": {
            "type": "custom"
        },
            "level2": {
            "type": "custom",
                "level3": {
                "type": "custom"
            },
                "level31": {
                "type": "notcustom"
            }
        }
    }
};
function getCustomFields(field, customFields) {
    var customFields = typeof customFields != "undefined" ? customFields : [];
    if (field["type"] == "custom") {
        customFields.push(field);
    }
    // Object.keys gets all own object property names as an array
    // in order to use filter to do a "where" the fieldName starts with
    // "level" word. Once every "level" property is filtered, you execute
    // an Array.forEach to execute the enclosing functin against the
    // inner level giving each level field and current customFields array
    // to accumulate results...
    Object.keys(field).filter(function (fieldName) {
        return fieldName.indexOf("level") == 0;
    }).forEach(function (levelPropertyName) {
        getCustomFields(field[levelPropertyName], customFields);
    });
    
    return customFields;
}
var customFields = getCustomFields(obj.fields);
document.getElementById("result").textContent = JSON.stringify(customFields);
<div id="result"></div>