要解析为JSON的数组条目
什么是最好的方法 - 正则表达式或其他东西?要解析为JSON的数组条目
我有以下阵列:
[
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
]
我需要开始 “B1:” 采取品牌B1从入门 这应该被解析,如:
{
"number": 1,
"category": "bottoms",
"height": "175",
"chest": 85,
"brand": "b1",
"hip": 90,
"size_1": "m",
"size_2": "m",
"size_3": "s"
}
编辑: 我需要只解析以“b1:number /”开头的数据。像数据一样
[
"b1:another/somethingElse", //SHOULD NOT BE CONSIDERED
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
]
我的想法是使用.reduce()
处理阵列中的每个元素,并添加其值的一个对象。 I .split()
/
字符上的每个项目,然后测试生成的片断数量以确定如何处理它。
function processItem(item) {
return item.reduce(function(a, v) {
var parts = v.split("/");
var b = parts[0].split(":");
if (b[1] === "number") {
switch(parts.length) {
case 2:
a[b[1]] = parts[1];
a.brand = b[0];
break;
case 4:
a[parts[2]] = +parts[3]; // note unary plus to convert to number
break;
case 6:
if (!a[parts[2]])
a[parts[2]] = parts[3];
a[parts[4]] = parts[5];
break;
}
}
return a;
}, {});
}
console.log(processItem([
"b1:another/somethingElse",
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:another/blah",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
]));
一般来说,没有一个很好的输入格式描述,会有很多假设烘焙到代码中。以下是我所做的一些值得大声呼吁的假设:
- 数组中只有一个“类别”。
- 不属于“类别”(即“胸部”,“身高”和“臀部”)的属性意味着整数。
- 类别下的属性(例如“size_1”等)是字符串。
- 具有五个或更多段的任何内容都是输入形式(看起来像/ category ///)。或者,您可以测试
split[2] == 'category'
并使用不匹配的字符串执行其他操作。 - 每个字符串以2个字符的前缀开头,即“品牌”。或者,您可以抓住一切,直到第一个冒号,或者只在特定行上寻找。
下面的代码:
data = [
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
];
var properties = {};
properties.brand = data[0].substr(0, 2);
for (var i = 0; i < data.length; i++) {
var split = data[i].split('/');
var category = null;
// Skip entries that don't have any real data
if (split.length > 2) {
if (split.length < 6) {
// e.g. b1:number/1/chest/85
properties[split[2]] = parseInt(split[3]);
} else {
// e.g. b1:number/1/category/bottoms/size_1/m
properties.category = split[3]; // e.g. bottoms
properties[split[4]] = split[5]; // e.g. size_1, m
}
} else if (split[0].split(':')[1] === 'number') {
properties.number = split[1];
}
}
console.log(properties);
// Output:
// { brand: 'b1',
// number: '1',
// chest: 85,
// height: 175,
// hip: 90,
// category: 'bottoms',
// size_2: 'm',
// size_1: 'm',
// size_3: 's' }
输入数据和结果有一个模式,所以这是一个变换操作。由于输入非常简单,您可以简单地使用split
函数将其切割成小块,然后构建输出。
请注意,您还需要进行类型转换和必要的验证。例如,身高是数字,所以不要忘记拨打Number
。
function numOrStr(s) {
return isNaN(s) ? s : Number(s)
}
function convert(input) {
try {
var arr = input[0].split(':')
var brand = arr[0]
arr = arr[1].split('/')
var result = {
brand: brand,
number: Number(arr[1])
}
input.slice(1).forEach(function(item) {
item = item.substr((input[0] + '/').length)
var arr = item.split('/')
if (arr[0] === 'category') {
result['category'] = arr[1]
result[arr[2]] = numOrStr(arr[3])
} else {
result[arr[0]] = numOrStr(arr[1])
}
})
return result
} catch (ex) {
console.error({msg: 'invalid input object', data: input})
}
}
var input = [
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
]
var output = convert(input)
console.log(output)
这是纯PHP方式:
<?php
$arr_ = [
"number/1",
"number/1/chest/85",
"number/1/height/175",
"number/1/hip/90",
"number/1/category/bottoms/size_2/m",
"number/1/category/bottoms/size_1/m",
"number/1/category/bottoms/size_3/s",
];
$arr_values = array();
for($i=0; $i <count($arr_); $i++){
$arr_data = explode("/", $arr_[$i]);
for($j=0; $j<count($arr_data); $j++){
if(!is_null($arr_data[($j + 1)])){
if(!in_array(array($arr_data[$j] => $arr_data[$j + 1]), $arr_values)){
array_push($arr_values, array($arr_data[$j] => $arr_data[($j + 1)]));
}
}
$j++;
}
}
echo json_encode($arr_values);
OUTPUT:
[{"number":"1"},{"chest":"85"},{"height":"175"},{"hip":"90"},{"category":"bottoms"},{"size_2":"m"},{"size_1":"m"},{"size_3":"s"}]
我想JS。抱歉不是php。 – Nisha
没有任何的正则表达式我如下可能做到这一点;
var data = [
"b1:number/1",
"b1:number/1/chest/85",
"b1:number/1/height/175",
"b1:number/1/hip/90",
"b1:number/1/category/bottoms/size_2/m",
"b1:number/1/category/bottoms/size_1/m",
"b1:number/1/category/bottoms/size_3/s",
"b1:notnumber/1/category/bottoms/size_4/xs"
],
dataObj = data.map(e => e.split(":"))
.map(e => ["brand",e[0]].concat(e[1].indexOf("number") === 0 ? e[1].split("/") :[]))
.map(e => e.reduce((p,c,i,a) => i%2 === 0 ? (p[c] = a[i+1],p) : p,{}))
.reduce((p,c) => Object.assign(p,c));
console.log(dataObj);
解释的代码:
.map(e => e.split(":"))
这将通过一个处理数据阵列的一个的每个元素,从":"
字符分割字符串的项目,并把每个子字符串转换成新的数组。所以输入阵列将被转换成一个二维数组像[["b1","number/1"],["b1","number/1/chest/85"],..., ["b1",notnumber/1/category/bottoms/size_4/xs"]]
.map(e => ["brand",e[0]].concat(e[1].indexOf("number") === 0 ? e[1].split("/") :[]))
这是sligtly复杂的部分。每个数据数组项是由映射函子内的e[0]
和e[1]
指定的两个元素的数组。我们将构造一个数组,其中偶数索引处的项目将用于目标对象的属性,而奇数索引处的项目将用作值。因此,我们从数组["brand",e[0]]
开始,其中e[0]
是"b1"
在这种特定情况下。然后,如果e[1]
处的字符串以"number"
(e[1].indexOf("number") === 0
)开始,那么我们通过使用"/"
字符将字符串拆分为数组。 (e[1].split("/")
)并获得"number/1/category/bottoms/size_2/m"
→["number", "1", "category", "bottoms", "size_2", "m"]
但是如果它不以"number"
开始,那么我们使用空数组[]
。最后,我们从concatanate e[0]
获得的两个阵列和e[1]
.map(e => e.reduce((p,c,i,a) => i%2 === 0 ? (p[c] = a[i+1],p) : p,{}))
这是标准的降低在上述阶段得到的阵列上操作。我们正在减少初始值(空对象){}
。每个偶数索引位置的项目(i%2 === 0
)都会作为属性添加到我们的初始对象,并且以下属性将作为此属性p[c] = a[i+1]
的值添加。然后我们返回p来提供reduce迭代的下一个阶段。 ,p) : p
.reduce((p,c) => Object.assign(p,c));
现在,我们已经按照数据阵列的每个项目的对象。我们将它们合并为一个。 Object.assign()
是这项工作的理想工具。
最后我们在链的末尾返回结果。
这对于正则表达式看起来很不错。 转换您的阵列到JS对象可以用这个来完成:
查找开始B1每个数组元素:数量,而忽略其他
\"(((?=b1:number).*[:,/](.*)\/(.*))|(?!>b1:number).*)\"
然后用最后2组 - 前和最后一个斜线后 - 为取代
"$3":"$4"
它将产生JS对象 - 只需仍包裹在阵列括号和用空的“属性”
[ "":"", "number":"1", "chest":"85", "height":"175", "hip":"90", "size_2":"m", "size_1":"m", "size_3":"s", ]
然后用花代替阵列括号:
"[test]".replace("[", "{").replace("]","}").replace(/"":"",/g, "");;
而且finaly您需要自定义的逻辑来处理,如果需要,甚至在适当的JS数据类型。
好的,查看我编辑的答案 –
我认为你的意思是JavaScript对象而不是“JSON对象”。除非你打算解析这个并把它放在一个.json文件中。 –
“胸”,“身高”,“臀围”和“类别”是第三级唯一的可能性吗?并且胸部/身高/臀部总是出现在*类别信息之前*你的示例数组很小。真实数据中有多少元素? – nnnnnn
在一个特定的api响应中,我只需要解析这个上面的数组。它仅在不同的API调用的值上有所不同。基本上结构是相似的。 @nnnnnn – Nisha