【问题标题】:Recursively list all object property paths from JSON [duplicate]递归列出来自 JSON 的所有对象属性路径 [重复]
【发布时间】:2015-07-28 23:45:59
【问题描述】:

我必须与 JSON 返回作斗争(我从 Amazon Marketplace API 的 XML 响应中得到)。它包含数组、子数组等。目前我只需要获取 2 个值(AmazonOrderId 和 OrderItem 对象),但我找不到直接解决它们的方法。我仍然尝试了几个小时。递归的东西让我有点害怕。

那里有很多工具,也可以用于美化或编辑 JSON。那么是否还有一种解决方案可以递归地显示所有属性链接?到目前为止,我还没有找到类似的东西。

更新:使用 squint 回答的代码,我构建了一个快速而肮脏的工具,可以满足我的需求。这里是:http://output.jsbin.com/gunixo

喜欢:

myJSON.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityOrdered
myJSON.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].Title
...

在这种情况下,这确实可以节省时间。

    {
    "ListOrderItemsResponse": {
        "$": {
            "xmlns": "https://mws.amazonservices.com/Orders/2013-09-01"
        },
        "ListOrderItemsResult": [{
            "OrderItems": [{
                "OrderItem": [{
                    "QuantityOrdered": ["1"],
                    "Title": ["My Product Title"],
                    "ShippingTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "PromotionDiscount": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ConditionId": ["New"],
                    "ASIN": ["BXXXI5W6M8"],
                    "SellerSKU": ["KNDR-BTTWSCH-BGSBNNY"],
                    "OrderItemId": ["67050234000659"],
                    "GiftWrapTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "QuantityShipped": ["1"],
                    "ShippingPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["4.90"]
                    }],
                    "GiftWrapPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ConditionSubtypeId": ["New"],
                    "ItemPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["15.77"]
                    }],
                    "ItemTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ShippingDiscount": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }]
                }]
            }],
            "AmazonOrderId": ["304-6107803-0000000"]
        }],
        "ResponseMetadata": [{
            "RequestId": ["dd64dd40-d939-4ea1-875d-xxxxxxxxxxxx"]
        }]
    }
}

【问题讨论】:

  • 如果是 XML 响应,为什么要将其转换为 JSON?为什么不寻找一种工具来遍历原始 XML 呢? XML 和 JSON 的数据类型和结构确实不能很好地相互映射,因此通过转换,您只会使底层结构的工作变得更加困难。
  • 另外,我不确定你在纠结什么;您提供的两个示例行看起来可以很好地处理您提供的示例数据。实际上不需要递归,只需对结构进行大量嵌套访问即可。
  • 感谢您的评论。我使用 MWS-JS-2014 从亚马逊连接和检索数据。这(仅)为我提供了一个 JSON 对象。
  • 是的,我很幸运,这两个确实有效。但是要找到正确的属性链接是很麻烦的。这些示例是其中的 2 个。获得较低属性的链接更难,因为我失去了概述。也因为有些属性有对象,有些有数组,有些只有值……昨天我花了几个小时没有找到正确的链接。我也没有找到向我显示此类属性链接的 Web 服务。但在这种情况下,这样的事情真的会有所帮助。

标签: javascript json node.js object amazon-mws


【解决方案1】:

如果你真的只需要这两个值,你可以在它被解析的时候做。

var data = {};

// ----------v--- Original JSON data before parsing.
JSON.parse(myJSON, function(k, v) {
    if (k === "AmazonOrderId" || k === "OrderItem") {
        data[k] = v;
    }
    return v;
});

也就是说……递归的东西不应该是可怕的。 StackOverflow 上有许多预先编写的函数,它们接受您要查找的属性并返回值,因此您可以只使用其中一个。


这是一个简单的递归函数,可以生成所有数据的路径。

function objectToPaths(data) {
  var validId = /^[a-z_$][a-z0-9_$]*$/i;
  var result = [];
  doIt(data, "");
  return result;

  function doIt(data, s) {
    if (data && typeof data === "object") {
      if (Array.isArray(data)) {
        for (var i = 0; i < data.length; i++) {
          doIt(data[i], s + "[" + i + "]");
        }
      } else {
        for (var p in data) {
          if (validId.test(p)) {
            doIt(data[p], s + "." + p);
          } else {
            doIt(data[p], s + "[\"" + p + "\"]");
          }
        }
      }
    } else {
      result.push(s);
    }
  }
}

所有 Array 成员都单独列出。如果您知道这些数组成员中的数据结构始终相同,则可以将其合并。

您的数据结果:

.ListOrderItemsResponse.$.xmlns
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityOrdered[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].Title[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].PromotionDiscount[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].PromotionDiscount[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ConditionId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ASIN[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].SellerSKU[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].OrderItemId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityShipped[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ConditionSubtypeId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingDiscount[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingDiscount[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].AmazonOrderId[0]
.ListOrderItemsResponse.ResponseMetadata[0].RequestId[0]

【讨论】:

  • 感谢您的回答,但这会引发JSON.parse(myJSON, function(k, v) { 行的错误:SyntaxError: Unexpected token o
  • 顺便说一句:您将我的问题标记为重复。您链接的答案可能会有所帮助,但这不是我问题的答案。我知道stackoverflow上有很多预先编写的函数。我经常利用这些功能作为快速解决方案。我敢肯定,有时我没有正确的关键字来找到我正在寻找的解决方案。无论如何,我的问题不是代码 sn-p。我已经要求列出给定 JSON 的属性链接或路径的网站/网络服务。我已经搜索了更多,但不幸的是我没有找到这个。但我发现了一个类似的请求:github.com/josdejong/jsoneditor/issues/168
  • @Lutz:您收到错误是因为您没有传递 JSON。见上面的代码注释。
  • 您描述了一个问题,而副本显示了一个解决方案。仅仅因为您认为特定的解决方案更好并不意味着其他答案不合格。 StackOverflow 不是第 3 方资源推荐服务。这是针对特定编程问题的问题。如果您没有询问实际问题,而是尝试实现这样的服务并陷入特定的问题,那么情况会有所不同。
  • 但我将 myJASON 作为第一个参数传递给 JSON.parse 函数。这个函数返回的不是 v 的东西吗?
猜你喜欢
  • 2016-10-16
  • 1970-01-01
  • 2021-12-26
  • 2016-06-02
  • 1970-01-01
  • 2021-05-01
  • 2011-02-10
  • 2021-12-31
  • 2019-01-04
相关资源
最近更新 更多