按值访问嵌套 JSON 数组
Access by value on nested JSON arrays
我是 JavaScript 的新手,我真的迷路了。以下是 PHP json_encode()
生成的一些数据(并且仅限于最相关的键):
[
{
"product_option_id":"229",
"product_option_value":
[
{
"product_option_value_id":"21",
"option_value_id":"51",
"price":"1,22 €",
"price_prefix":"+"
},
{
"product_option_value_id":"22",
"option_value_id":"52",
"price":false,
"price_prefix":"+"
},
{
"product_option_value_id":"23",
"option_value_id":"53",
"price":"2,42 €",
"price_prefix":"+"
}
],
"option_id":"14",
"type":"radio",
"value":""
},
{
"product_option_id":"228",
"product_option_value":
[
{
"product_option_value_id":"19",
"option_value_id":"49",
"price":"1,22 €",
"price_prefix":"+"
},
{
"product_option_value_id":"20",
"option_value_id":"50",
"price":"2,42 €",
"price_prefix":"+"
}
],
"option_id":"13",
"type":"select",
"value":""
}
]
我需要访问 price
和 price_prefix
值(在 JavaScript 中)知道 product_option_id
和 product_option_value_id
。
我该怎么做?我应该去循环吗?
更新:
感谢您的回复。除非我遗漏了什么,否则 in my case arrays (as ugly as they may be…) are much more efficient 似乎比所有建议的解决方案都好(我将尝试另一种方法,使用 PHP 格式化符合我需求的 JSON 对象,而不是使用 "default" 一个,但这是题外话)。尽管我不喜欢添加库,而且它比大多数其他解决方案都要慢一些,但我还是会接受 Matt 的解决方案,因为就 JSON 访问而言,它似乎确实让生活变得更轻松。但需要注意的是,Yeldard 和 Barmar 的(几乎是克隆的)解决方案比其他命题更快。
你可以这样做
for(var i in jsonData) {
var item = jsonData[i];
if(item.product_option_id == 229) {
for(var j in item.product_option_value){
var item1 = item.product_option_value[j];
if(item1.product_option_value_id == 21) {
//your item here
break;
}
}
break;
}
}
应该这样做:
var productOptionId = 229;
var productOptionValue = 22;
var matchingOuter = yourData.filter(function(i){
return i.product_option_id === productOptionId;
})[0];
if (matchingOuter) {
var matchingInner = matchingOuter.product_option_value.filter(function(i){
return i.product_option_value === productOptionValue;
})[0];
}
如果存在匹配项,它将被分配给 matchingInner
是的,您需要枚举数组并找到您的项目:
这是输出 price_prefix
和 price
产品 product_option_id
= 228 和 product_option_value_id
= 19 的工作代码。您可以用自己的值替换这些值.
for (var i = 0; i < obj.length; i++) // Enumerate through array
{
var item = obj[i];
if (item.product_option_id === "228") // Filtering items by product_option_id
{
// When necessary product_option_id found
for (var j = 0; j < item.product_option_value.length; j++) // Enumerate through its products
{
var productItem = item.product_option_value[j];
if (productItem.product_option_value_id === "19") // Filtering by product_option_value_id
{
// here it is. productItem is found! do whatever you want with it
alert(productItem.price_prefix + " " + productItem.price);
}
}
}
}
使用嵌套循环搜索主数组和子数组,寻找匹配的元素。
function find_product(product_option_id, product_option_value_id) {
for (var i = 0; i < products.length; i++) {
var product = products[i];
if (product.product_option_id == product_option_id) {
for (var j = 0; j < product.product_option_value.length; j++) {
var value = product.product_option_value[j];
if (value.product_option_value_id == product_option_value_id) {
return { price: value.price, price_prefix: value.price_prefix }
}
}
}
}
}
在 returned 数组上使用 filter
on the main array to grab the right object, filter again on the option_value_id, then map
以获得单个 price/prefix 对象。 map
和 filter
都是 return 数组,这就是为什么您看到代码在几个地方拾取第一个元素 ([0]
) 的原因。
function getData(data, options) {
return data.filter(function (product) {
return product.product_option_id === options.id;
})[0].product_option_value.filter(function (details) {
return details.product_option_value_id === options.optionId;
}).map(function(el) {
return { price: el.price, prefix: el.price_prefix }
})[0];
}
getData(data, { id: '229', optionId: '23' }); // { price: "2,42 €", prefix: "+" }
执行以下操作:
function getProductValues(products, product_option_id, product_option_value_id) {
if (!product_option_id || !product_option_value_id) {
return;
}
return products.filter(function(product) {
return +product.product_option_id === product_option_id;
}).map(function (product) {
var option_values = product.product_option_value;
return option_values.filter(function (option) {
return +option.option_value_id === product_option_value_id;
})[0] || [];
})[0] || [];
}
用法:
getProductValues(data, 229, 51)
结果:
{product_option_value_id: "21", option_value_id: "51", price: "1,22 €", price_prefix: "+"}
lodash would make this easier and neater. It provides _.find
or _.filter
取决于您的 ID 是否唯一。
var record = _.find( data_structure, {
"product_option_id": "229"
})
if ( !record ) throw new Error("Record not found");
var value = _.find( record.product_option_value, {
"product_option_value_id":"22"
})
if ( !value ) throw new Error("Value not found");
console.log( "price[%s] prefix[%s]", value.price, value.price_prefix )
对于更复杂的数据选择,您可能需要查看 sift.js. It's based on mongodb's query system。
var records = sift({
"product_option_id": "229",
"product_option_value": {
$elemMatch: {
"product_option_value_id": "22"
}
}
},
data_structure
)
我是 JavaScript 的新手,我真的迷路了。以下是 PHP json_encode()
生成的一些数据(并且仅限于最相关的键):
[
{
"product_option_id":"229",
"product_option_value":
[
{
"product_option_value_id":"21",
"option_value_id":"51",
"price":"1,22 €",
"price_prefix":"+"
},
{
"product_option_value_id":"22",
"option_value_id":"52",
"price":false,
"price_prefix":"+"
},
{
"product_option_value_id":"23",
"option_value_id":"53",
"price":"2,42 €",
"price_prefix":"+"
}
],
"option_id":"14",
"type":"radio",
"value":""
},
{
"product_option_id":"228",
"product_option_value":
[
{
"product_option_value_id":"19",
"option_value_id":"49",
"price":"1,22 €",
"price_prefix":"+"
},
{
"product_option_value_id":"20",
"option_value_id":"50",
"price":"2,42 €",
"price_prefix":"+"
}
],
"option_id":"13",
"type":"select",
"value":""
}
]
我需要访问 price
和 price_prefix
值(在 JavaScript 中)知道 product_option_id
和 product_option_value_id
。
我该怎么做?我应该去循环吗?
更新:
感谢您的回复。除非我遗漏了什么,否则 in my case arrays (as ugly as they may be…) are much more efficient 似乎比所有建议的解决方案都好(我将尝试另一种方法,使用 PHP 格式化符合我需求的 JSON 对象,而不是使用 "default" 一个,但这是题外话)。尽管我不喜欢添加库,而且它比大多数其他解决方案都要慢一些,但我还是会接受 Matt 的解决方案,因为就 JSON 访问而言,它似乎确实让生活变得更轻松。但需要注意的是,Yeldard 和 Barmar 的(几乎是克隆的)解决方案比其他命题更快。
你可以这样做
for(var i in jsonData) {
var item = jsonData[i];
if(item.product_option_id == 229) {
for(var j in item.product_option_value){
var item1 = item.product_option_value[j];
if(item1.product_option_value_id == 21) {
//your item here
break;
}
}
break;
}
}
应该这样做:
var productOptionId = 229;
var productOptionValue = 22;
var matchingOuter = yourData.filter(function(i){
return i.product_option_id === productOptionId;
})[0];
if (matchingOuter) {
var matchingInner = matchingOuter.product_option_value.filter(function(i){
return i.product_option_value === productOptionValue;
})[0];
}
如果存在匹配项,它将被分配给 matchingInner
是的,您需要枚举数组并找到您的项目:
这是输出 price_prefix
和 price
产品 product_option_id
= 228 和 product_option_value_id
= 19 的工作代码。您可以用自己的值替换这些值.
for (var i = 0; i < obj.length; i++) // Enumerate through array
{
var item = obj[i];
if (item.product_option_id === "228") // Filtering items by product_option_id
{
// When necessary product_option_id found
for (var j = 0; j < item.product_option_value.length; j++) // Enumerate through its products
{
var productItem = item.product_option_value[j];
if (productItem.product_option_value_id === "19") // Filtering by product_option_value_id
{
// here it is. productItem is found! do whatever you want with it
alert(productItem.price_prefix + " " + productItem.price);
}
}
}
}
使用嵌套循环搜索主数组和子数组,寻找匹配的元素。
function find_product(product_option_id, product_option_value_id) {
for (var i = 0; i < products.length; i++) {
var product = products[i];
if (product.product_option_id == product_option_id) {
for (var j = 0; j < product.product_option_value.length; j++) {
var value = product.product_option_value[j];
if (value.product_option_value_id == product_option_value_id) {
return { price: value.price, price_prefix: value.price_prefix }
}
}
}
}
}
在 returned 数组上使用 filter
on the main array to grab the right object, filter again on the option_value_id, then map
以获得单个 price/prefix 对象。 map
和 filter
都是 return 数组,这就是为什么您看到代码在几个地方拾取第一个元素 ([0]
) 的原因。
function getData(data, options) {
return data.filter(function (product) {
return product.product_option_id === options.id;
})[0].product_option_value.filter(function (details) {
return details.product_option_value_id === options.optionId;
}).map(function(el) {
return { price: el.price, prefix: el.price_prefix }
})[0];
}
getData(data, { id: '229', optionId: '23' }); // { price: "2,42 €", prefix: "+" }
执行以下操作:
function getProductValues(products, product_option_id, product_option_value_id) {
if (!product_option_id || !product_option_value_id) {
return;
}
return products.filter(function(product) {
return +product.product_option_id === product_option_id;
}).map(function (product) {
var option_values = product.product_option_value;
return option_values.filter(function (option) {
return +option.option_value_id === product_option_value_id;
})[0] || [];
})[0] || [];
}
用法:
getProductValues(data, 229, 51)
结果:
{product_option_value_id: "21", option_value_id: "51", price: "1,22 €", price_prefix: "+"}
lodash would make this easier and neater. It provides _.find
or _.filter
取决于您的 ID 是否唯一。
var record = _.find( data_structure, {
"product_option_id": "229"
})
if ( !record ) throw new Error("Record not found");
var value = _.find( record.product_option_value, {
"product_option_value_id":"22"
})
if ( !value ) throw new Error("Value not found");
console.log( "price[%s] prefix[%s]", value.price, value.price_prefix )
对于更复杂的数据选择,您可能需要查看 sift.js. It's based on mongodb's query system。
var records = sift({
"product_option_id": "229",
"product_option_value": {
$elemMatch: {
"product_option_value_id": "22"
}
}
},
data_structure
)