我们正在使用Postman进行API测试。我们返回的某些对象非常冗长且不易处理,因此我想创建一个辅助方法以使它们更加简洁。我知道有各种各样的转换库,例如node-json-transform,selecttransform,jsontransforms等,但是不幸的是,我只能使用Postman Sandbox libraries和普通JS。
我正在寻找最简单的方法(最少loc和函数)来转换此对象:
var verbose = [
{
"Key": "Name",
"Value": "John Doe",
"Instance": 1
},
{
"Key": "Age",
"Value": "33",
"Instance": 1
},
{
"Key": "Child",
"Value": "Jane",
"Instance": 1
},
{
"Key": "Child",
"Value": "Rocky",
"Instance": 2
}];
对此:
var concise = {
"Name": "John Doe",
"Age": "33",
"Child": ["Jane", "Rocky"]
};
,然后又回到详细形式。
我已经尝试了遍历每个对象并将属性/值添加到新对象的本机方法,但是当我到达多个实例键/值对时,这种方法很快就变得难看了。我可以想象有一种使用map / reduce的简便方法,但是我不熟悉那些方法。
答案 0 :(得分:2)
根据我对您问题的理解,您想从verbose
对象数组中创建键/值对。但是,如果存在键冲突,则应将值转换为数组。
考虑到这一点,您将必须:
forEach
遍历对象数组。请参见下面的概念验证:
var verbose = [{
"Key": "Name",
"Value": "John Doe",
"Instance": 1
},
{
"Key": "Age",
"Value": "33",
"Instance": 1
},
{
"Key": "Child",
"Value": "Jane",
"Instance": 1
},
{
"Key": "Child",
"Value": "Rocky",
"Instance": 2
}];
var concise = {};
verbose.forEach(function(i) {
var key = i['Key'];
var value = i['Value'];
// If item exists, we want to convert the value into an array of values
if (key in concise) {
var item = concise[key];
// If it is not an array already, we convert it to an array
if (!Array.isArray(item))
item = [item];
item.push(value);
concise[key] = item;
}
// If item does not exist, we simply create a new key-value pair
else {
concise[key] = value;
}
});
console.log(concise);
答案 1 :(得分:1)
您可以这样做:
const verbose = [{"Key": "Name","Value": "John Doe","Instance": 1},{"Key": "Age","Value": "33","Instance": 1},{"Key": "Child","Value": "Jane","Instance": 1},{"Key": "Child","Value": "Rocky","Instance": 2}];
const concise = Object.values(verbose.reduce((a, {Key, Value}) => (Key === 'Child' ? a.childs[0].Child.push(Value) : a.keys.push({[Key]: Value}), a), {keys: [], childs: [{Child: []}]})).flat(1);
console.log(concise);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:1)
const verbose = [{
"Key": "Name",
"Value": "John Doe",
"Instance": 1
},
{
"Key": "Age",
"Value": "33",
"Instance": 1
},
{
"Key": "Child",
"Value": "Jane",
"Instance": 1
},
{
"Key": "Child",
"Value": "Rocky",
"Instance": 2
}
];
let concise = {};
verbose.forEach(item => {
const values = Object.values(item)
if (concise[values[0]]) concise = {...concise, [values[0]]: [concise[values[0]], values[1]]};
else concise = {...concise, ...{[values[0]]: values[1]}}
})
答案 3 :(得分:1)
尝试一下。我已经写了两个转换函数。 我看到其他答案仅提供了简洁明了的要求。
let verbose = [{
"Key": "Name",
"Value": "John Doe",
"Instance": 1
},
{
"Key": "Age",
"Value": "33",
"Instance": 1
},
{
"Key": "Child",
"Value": "Jane",
"Instance": 1
},
{
"Key": "Child",
"Value": "Rocky",
"Instance": 2
}
]
let concise = {
"Name": "John Doe",
"Age": "33",
"Child": ["Jane", "Rocky"]
}
verboseToConcise = (verbose) => {
let obj = {}
verbose.forEach(v => {
let key = obj[v.Key]
if (key) typeof key === 'string' ? obj[v.Key] = [key, v.Value] : key.push(v.Value)
else obj[v.Key] = v.Value
})
return obj
}
conciseToVerbose = (concise) => {
let arr = []
Object.entries(concise).forEach(([key, value]) => {
if (typeof value === 'object') {
for (let i = 0; i < value.length; i++){
arr.push({
"Key": key,
"Value": value[i],
"Instance": i+1
})
}
} else {
arr.push({
"Key": key,
"Value": value,
"Instance": 1
})
}
})
return arr
}
console.log(verboseToConcise(verbose))
console.log(conciseToVerbose(concise))
答案 4 :(得分:1)
在这里,我假设所有属性都是多值的,然后将长度为1的那些属性简化为简单值。这比反向方法要慢一些,在反向方法中,您假设值是单值的,并在证明相反的情况下将它们提升为数组,以遵守Instance
施加的顺序。
function makeConcise(verbose) {
let concise = {};
verbose.forEach(({Key, Value, Instance}) => {
if (!concise[Key]) concise[Key] = [];
concise[Key][Instance - 1] = Value;
});
Object.keys(concise).forEach(Key => {
if (concise[Key].length == 1) concise[Key] = concise[Key][0];
});
return concise;
}
反向功能同样简单:
function makeVerbose(concise) {
let verbose = [];
Object.keys(concise).forEach(Key => {
if (Array.isArray(concise[Key])) {
concise[Key].forEach((Value, index) => {
verbose.push({Key, Value, Instance: index + 1});
});
} else {
verbose.push({Key, Value: concise[Key], Instance: 1});
}
});
return verbose;
}
答案 5 :(得分:1)
我也尝试使用reduce
:
编辑:不使用...
扩展语法,而使用Object.assign
和array.concat
EDIT2:我想尝试再次将其重新打开。在这段代码中,我们丢失了Instance
:(
var verbose = [
{
Key: 'Name',
Value: 'John Doe',
Instance: 1,
},
{
Key: 'Age',
Value: '33',
Instance: 1,
},
{
Key: 'Child',
Value: 'Jane',
Instance: 1,
},
{
Key: 'Child',
Value: 'Rocky',
Instance: 2,
},
]
const concise = verbose.reduce(
(p, n) =>
Object.assign(p, {
[n.Key]: !p.hasOwnProperty(n.Key)
? n.Value
: typeof p[n.Key] === 'string'
? [p[n.Key], n.Value]
: p[n.Key].concat(n.Value),
}),
{},
)
console.log(concise)
// { Name: 'John Doe', Age: '33', Child: [ 'Jane', 'Rocky' ] }
const backAgain = Object.entries(concise).reduce(
(p, [k, v]) =>
Array.isArray(v)
? p.concat(v.map(x => ({ Key: k, Value: x })))
: p.concat({ Key: k, Value: v }),
[],
)
console.log(backAgain)
// [ { Key: 'Name', Value: 'John Doe' },
// { Key: 'Age', Value: '33' },
// { Key: 'Child', Value: 'Jane' },
// { Key: 'Child', Value: 'Rocky' } ]