在 JSON 中使用动态多维键值对
Posted
技术标签:
【中文标题】在 JSON 中使用动态多维键值对【英文标题】:Working With Dynamic Multidimensional key-value pairs in JSON 【发布时间】:2015-11-05 16:25:48 【问题描述】:遇到一个棘手的问题,只看到类似但也更简单的 SO 解决方案。
是否可以使用 JS/JSON 生成动态键和动态值?
例如,假设我有这样的 JSON:
"email": "user@someco.com",
"firstname": "Bob",
"lastname": "Smith",
"company": "ACME",
"custom":
"services": [
"name": "svc1",
"desc": "abcdefg",
"selected": "true",
"status": "None"
,
"name": "svc2",
"desc": "abcdefg",
"selected": "true",
"status": "None"
,
"name": "svc3",
"desc": "abcdefg",
"selected": "false",
"status": "None"
,
"name": "svc4",
"desc": "abcdefg",
"selected": "false",
"status": "None"
],
"fields": [
"name": "Products",
"desc": "abcdef",
"type": "multi",
"values": [
"name": "Product1",
"desc": "abcdef"
,
"name": "Product2",
"desc": "abcdef"
],
"services": [
"svc1",
"svc2",
"svc3"
]
,
"name": "Wines",
"desc": "abcdef",
"type": "multi",
"values": [
"name": "Wine 1",
"desc": "abcdef"
],
"services": [
"svc4"
]
,
"name": "Fruits",
"desc": "abcdef",
"type": "multi",
"values": [
"name": "Fruit 1",
"desc": "abcdef"
,
"name": "Fruit 2",
"desc": "abcdef"
],
"services": [
"svc4"
]
]
;
我需要进入各个领域并针对每个领域(产品、葡萄酒、水果)查看是否包含给定的服务,以便我可以返回并为需要它的每项服务生成产品或葡萄酒或水果。但我不想多次重复服务名称。生成的 JSON 应如下所示:
"svc1":["Products"], "svc2":["Products"], "svc3":["Products"], "svc4":["Fruits", "Wines"]
希望在 Angular 中生成一个动态列表,我可以通过这个 JSON 循环返回,提取每个产品、水果、葡萄酒等的值。
我一直在尝试很多嵌套的 for 循环等,但每当我向下一层以上时,动态似乎就会停止。我猜要让它工作,我需要在 JS 对象和 JSON 之间移动?
现在我正在尝试这样的事情,无论是否进行字符串化,它都不太有效。也许我在 JSON 和 JS 对象之间来回切换太多:
var outObj = [];
var fieldItems;
$.each(jsonObj.custom.fields, function(key, item)
fieldItems = item;
fieldItems.name = item.name;
$.each(fieldItems.services, function(key, item)
var serviceName = item;
//check to see if the serviceName already exists
if (outObj.indexOf(serviceName) > -1)
outObj.serviceName.push(fieldItems.name);
else
outObj.push(serviceName);
);
);
JSON.stringify(outObj);
console.log("outObj " + outObj);
我收到“无法读取未定义的属性‘推送’”错误等。似乎这应该可以从一个嵌套循环中实现,但也许我只需要做两次传递?还有其他建议吗?
【问题讨论】:
if (outObj.indexOf(serviceName) > -1)
应该给你一个错误,对象没有 indexOf 方法。既然不是,我猜它不是一个对象,我们需要看看它是如何定义的以重现你的问题。
哎呀...忘记了那段代码,好电话。
哦...好吧,那outObj.indexOf(serviceName)
怎么没有失败。
盯着这个看太久了,我已经不再看到了……再次编辑。
【参考方案1】:
对我来说,这听起来像是过于复杂的解决方案。您可以使用 javascript 的基本数组方法来过滤掉所需的结构。我不确定提供的 sn-p 中的profiling_value
是什么,所以我从 OP 中的对象结构开始
var desiredResult = jsonObj.custom.services.reduce(function(result, service)
result[service.name] = jsonObj.custom.fields.filter(function(field)
return field.services.indexOf(service.name) >= 0;
).map(function(field) return field.name; );
return result;
, );
这给出了所提到对象的预期结果。
reduce
需要遍历所有服务并将结果累积到一个对象中。然后将每个服务字段迭代到filter
,仅列出那些包含该服务链接的字段。最后过滤字段列表被转换 (map
) 为字符串列表 - 它们的名称 - 并插入到累加器中
【讨论】:
无论我阅读了多少次文档,为什么我很难理解reduce
所做的事情
Gah...几年前艰难地学习了 JavaScript,尽管我对 jQuery 是这么认为的,但似乎从未忘记过旧的做事方式。得到减少(让我不要重复),得到过滤器......然后当然地图就从那里开始。基里尔,谢谢!
@KevinB,this MDN description 帮助了我。
也希望我能以某种方式更多地宣传这一点,因为这是一个很好的教训,当它们看起来很抽象时,一起使用 reduce、filter、map。以上是关于在 JSON 中使用动态多维键值对的主要内容,如果未能解决你的问题,请参考以下文章