使用underscore.js在深度嵌套的JSON中查找值

Using underscore.js to find values in deeply nested JSON

本文关键字:JSON 查找 嵌套 underscore js 深度 使用      更新时间:2023-09-26

我对Javascript很陌生,刚刚了解了underscore.js。我有一个嵌套很深的JSON对象,我需要使用下划线来查找键/值对,然后我将使用下划线来填充各种HTML表。如果结构更浅,使用_.pull之类的东西会很容易,但我只是不知道如何遍历前几个嵌套级别(即surveyGDB、表、表名)。JSON对象来自一个由多个嵌套结构(从不同的数据库表中混合而成)组成的XML。

var JSONData = 
"surveyGDB": {
      "filename": "..''Topo''SurveyGeoDatabase.gdb",
      "table": {
        "tablename": [
          {
            "#text": "SurveyInfo'n      ",
            "record": {
              "OBJECTID": "1",
              "SiteID": "CBW05583-345970",
              "Watershed": "John Day",
              "VisitType": "Initial visit",
              "SurveyInstrument": "Total Station",
              "ImportDate": "2015-07-22T09:08:42",
              "StreamName": "Duncan Creek",
              "InstrumentModel": "TopCon Magnet v2.5.1",
              "FieldSeason": "2015"
          }
        },
        {
          "#text": "QaQcPoints'n      ",
          "record": [
            {
              "OBJECTID": "1",
              "TIMESTAMP": "2015-07-22T09:18:43",
              "Code": "tp",
              "Count": "357"
            },
            {
              "OBJECTID": "2",
              "TIMESTAMP": "2015-07-22T09:18:43",
              "Code": "tb",
              "Count": "92"
            },
            {
              "OBJECTID": "3",
              "TIMESTAMP": "2015-07-22T09:18:43",
              "Code": "to",
              "Count": "8"
            },
            {
              "OBJECTID": "4",
              "TIMESTAMP": "2015-07-22T09:18:43",
              "Code": "bl",
              "Count": "279"
            },
            {
              "OBJECTID": "5",
              "TIMESTAMP": "2015-07-22T09:18:43",
              "Code": "bf",
              "Count": "18"
            }
          ]
        },
        {
          "#text": "QaQcPolygons'n      ",
          "record": [
            {
              "OBJECTID": "1",
              "TIMESTAMP": "2015-07-22T09:43:08",
              "SurveyExtentCount": "",
              "WaterExtentCount": "",
              "ChannelUnitsCount": "",
              "ChannelUnitsUnique": ""
            },
            {
              "OBJECTID": "2",
              "TIMESTAMP": "2015-07-22T13:35:15",
              "SurveyExtentCount": "1",
              "WaterExtentCount": "1",
              "ChannelUnitsCount": "21",
              "ChannelUnitsUnique": "21"
            }
          ]
        }
      ]
    }
  }
}

例如,我想要"QaQCPoints"表中"Code"的所有值,所以我尝试了:

var codes = _.flatten(_.pluck(JSONData.surveyGDB.table.tablename[1].record[0], "Code" ));
console.log(codes);

在控制台中,这将返回一个长度为5但值为空的数组。我做错了什么?

我也更愿意基于"#text"键值之类的东西在表中搜索"Code"值,而不是只使用它在对象中的位置。

如果我理解正确,您希望始终在JSONData.surveyGDB.table.tablename数组中的record数组中搜索一些查询。这意味着您需要根据某个参数找到记录,并从找到的记录中返回一些内容。

请注意,在您的示例中,record属性有时是数组,有时是对象(对于表SurveyInfo),因此我认为您需要考虑这一点。您可以制作一个小函数来提取数据并处理对象和数组:

function extract(record, prop) {
  if (Array.isArray(record)) { 
    return _.pluck(record, prop);
  } else {
    return record[prop];
  }
}

用法示例:

我想要"QaQCPoints"表中"Code"的所有值。我也更愿意基于"#text"键值之类的东西在表中搜索"Code"值,而不是只使用它在对象中的位置。

为了实现这一点,您首先使用_.find查找一条记录,然后使用上面的方法从中提取Code值:

var table = JSONData.surveyGDB.table.tablename;
// find an item that has `#text` property equal to `QaQcPoints`
var item = _.find(table, function(r) {
  return r['#text'] === 'QaQcPoints';
});
// extract codes from the found item's record property
var code = extract(item.record, 'Code');
// output ["tp", "tb", "to", "bl", "bf"]

运行样本:

var JSONData = {
  "surveyGDB": {
    "filename": "..''Topo''SurveyGeoDatabase.gdb",
    "table": {
      "tablename": [{
        "#text": "SurveyInfo",
        "record": {
          "OBJECTID": "1",
          "SiteID": "CBW05583-345970",
          "Watershed": "John Day",
          "VisitType": "Initial visit",
          "SurveyInstrument": "Total Station",
          "ImportDate": "2015-07-22T09:08:42",
          "StreamName": "Duncan Creek",
          "InstrumentModel": "TopCon Magnet v2.5.1",
          "FieldSeason": "2015"
        }
      }, {
        "#text": "QaQcPoints",
        "record": [{
          "OBJECTID": "1",
          "TIMESTAMP": "2015-07-22T09:18:43",
          "Code": "tp",
          "Count": "357"
        }, {
          "OBJECTID": "2",
          "TIMESTAMP": "2015-07-22T09:18:43",
          "Code": "tb",
          "Count": "92"
        }, {
          "OBJECTID": "3",
          "TIMESTAMP": "2015-07-22T09:18:43",
          "Code": "to",
          "Count": "8"
        }, {
          "OBJECTID": "4",
          "TIMESTAMP": "2015-07-22T09:18:43",
          "Code": "bl",
          "Count": "279"
        }, {
          "OBJECTID": "5",
          "TIMESTAMP": "2015-07-22T09:18:43",
          "Code": "bf",
          "Count": "18"
        }]
      }, {
        "#text": "QaQcPolygons",
        "record": [{
          "OBJECTID": "1",
          "TIMESTAMP": "2015-07-22T09:43:08",
          "SurveyExtentCount": "",
          "WaterExtentCount": "",
          "ChannelUnitsCount": "",
          "ChannelUnitsUnique": ""
        }, {
          "OBJECTID": "2",
          "TIMESTAMP": "2015-07-22T13:35:15",
          "SurveyExtentCount": "1",
          "WaterExtentCount": "1",
          "ChannelUnitsCount": "21",
          "ChannelUnitsUnique": "21"
        }]
      }]
    }
  }
}
function extract(record, prop) {
  if (Array.isArray(record)) {
   return _.pluck(record, prop);
  } else {
    return record[prop];
  }
}
var table = JSONData.surveyGDB.table.tablename;
var item = _.find(table, function(r) {
  return r['#text'] === 'QaQcPoints';
});
console.dir(item);
var code = extract(item.record, 'Code');
console.log(code);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

您有一个两阶段的问题。第一阶段是找出哪个表是QaQcPoints。如果始终是JSONData.surveyGDB.table.tablename],那就很好了。

下一阶段是获取数据。大多数时候都可以使用本机数组操作(除非您使用的是非常旧的浏览器)。因此:

var table = JSONData.surveyGDB.table.tablename[1].record;
var codeArray = table.map(function(val) { return val.Code; });

会成功的。