我是Ember和JSON的新手。我想使用typeahead库解析下面的JSON对象 并通过搜索其键来访问嵌套对象值。
我有这种Json格式:
return [
{
"id": 1,
"category_name": "Supermarket",
"category_description": "SUPER MARKET",
"image_url": "",
"merchants": [
{
"name": "CARREFOUR",
"id": 12,
"merchant_type_id": 1,
"merchant_type_description": "Gold",
"merchant_redeption_rate": 0.002500,
"image_url": "https://jpg",
"branches": [
{
"id": 123456,
"latitude": 37.939483,
"area": "ΑΓ. ΔΗΜΗΤΡΙΟΣ",
"zip": "12345"
},
{
"id": 4567890,
"longitude": 23.650622,
"area": "ΑΓ. ΙΩΑΝΝΗΣ ΡΕΝΤΗΣ",
"zip": "12345"
}
]
},
{
"name": "CAFCO",
"id": 13,
"merchant_type_id": 3,
"merchant_type_description": "None",
"merchant_redeption_rate": 0.002500,
"image_url": "https:.jpg",
"branches": [
{
"id": 127890,
"latitude": 38.027870,
"area": "ΠΕΡΙΣΤΕΡΙ",
"zip": "12345"
}
]
}
]
},
{
"id": 2,
"category_name": "Πολυκαταστήματα",
"category_description": "ΠΟΛΥΚΑΤΑΣΤΗΜΑ",
"image_url": "",
"merchants": [
{
"name": "AGGELOPOYLOS CHR.",
"id": 15,
"merchant_type_id": 2,
"merchant_type_description": "Silver",
"merchant_redeption_rate": 0.002500,
"image_url": "https://www.nbg.gr/greek/retail/cards/reward-programmes/gonational/PublishingImages/aggelopoulos.jpg",
"branches": [
{
"id": 234780,
"latitude": 35.366118,
"longitude": 24.479461,
"address": "ΕΘΝ. ΜΑΚΑΡΙΟΥ 9 & ΕΛ. ΒΕΝΙΖΕΛΟΥ 1",
"area": "Ν. ΦΑΛΗΡΟ",
"zip": "12345"
}
]
}
]
}
];
--------------------------的更新 ------------- ---------------
例如,我想使用typeahead搜索商家名称,当我们写入搜索的信件与商家名称匹配时,它将显示相应的category_name和向后。
示例 - >当我键入s时它会出现: 类别:超市, 姓名:CARREFOUR 名称:CAFCO
当我键入字母c时,搜索下拉列表中的输出相同。
任何帮助?
答案 0 :(得分:0)
最简单的方法(在我看来)让它工作是创建一个包含纬度数组的计算属性。但是我们如何到达那里?
要转到latitude
,您需要浏览merchants
数组,然后查看branches
数组。因为这将跨越多个元素,你将最终得到"阵列数组"类型数据结构,这是很烦人的处理。因此,为了简化这一点,我们可以创建一个简单的flatten
函数,如下所示:
flatten: function(origArray){
var newArr = [];
origArray.forEach(function(el) {
el.forEach(function(eachEl){
newArr.push(eachEl);
});
});
return newArr;
},
除了上面的函数,Ember还为我们提供了许多可用于数组的有用函数(参见here)。其中一个是mapBy(property)
,它将数组转换为另一个数组,只保留我们指定的属性的值。
因此,要创建lats
(纬度)属性,我们可以这样做:
lats: function(){
var merchantsArr = this.get('model').mapBy('merchants');
merchantsArr = this.flatten(merchantsArr);
var branchesArr = merchantsArr.mapBy('branches');
branchesArr = this.flatten(branchesArr);
return branchesArr.mapBy("latitude").compact();
}.property('model')
上面,我基本上使用mapBy
,flatten
(见上文)和compact
返回数组的副本,删除所有null和undefined元素。
一旦您拥有包含所有必要数据的lats
属性,其余的就很容易了。
您对组件的调用变为:
{{x-typeahead data=lats name='category_name' selection=myColor}}
注意lats
而不是您最初传入组件的model
。
现在,要访问组件中data
属性的值,请执行
`this.get('data')`
你可以像source
那样传递:
source: substringMatcher(self.get('data'))
工作解决方案here
<强>更新强>
根据您更新的问题更新我的答案。
好的,所以这会变得有点复杂。您现在需要的不仅仅是来自对象的一个属性(latitude
)。您需要category_name
和商家name
。
除了mapBy
,它只是从数组中获取一个属性之外,Ember还有map
,它允许您将数组转换为您想要的任何内容:
lats: function(){
var merchantsArr = this.get('model').map(function(thing){
var category_name = thing.category_name;
return thing.merchants.map(function(merchant){
return {
"name": merchant.name,
"category": category_name
};
});
});
merchantsArr = this.flatten(merchantsArr);
return merchantsArr;
}.property('model')
上面的代码看起来很复杂,但它基本上只返回一组顶级对象&#39;商人陪同category_name
。由于这是一个数组数组,我们需要将其展平。
然后,在组件内部,我们需要记住,我们不只是传入一个字符串数组,而是传入一个对象数组。因此,我们需要查看对象的属性(名称和类别)以进行匹配
$.each(strs, function(i, str) {
if (substrRegex.test(str.name) || substrRegex.test(str.category)) {
matches.push(str);
}
});
最后,要实际显示类别和商家名称,您需要告诉Typeahead如何执行此操作:
templates: {
suggestion: Handlebars.compile('<p>{{name}} – {{category}}</p>')
}
工作解决方案here