我正在处理我从数据库中检索的一些JSON
数据。如果结果包含单个值,则会创建单个对象。如果有多个值,则会创建一个对象数组。
我的问题是,在处理循环时,不得不尝试处理这个问题。
示例数据:
// Single result from DB
var obj = {
"records": {
"recordID": 1,
"recordName": 'test'
}
}
// Multiple results from DB
var obj = {
"records": [{
"recordID": 1,
"recordName": 'test'
}, {
"recordID": 2,
"recordName": 'test again'
}]
}
我有一个循环遍历所有记录的函数,当我们只有一个结果因为我们不再循环遍历数组时,这就成了问题。
由于我的一些对象非常大,我试图想出一个函数,当我在处理它之前从数据库中取回它时,我可以初始化我的对象。
此函数将循环遍历所有键并检查键是否存在于"数组中是否需要是数组?"标志。如果找到匹配项,请检查它是否是单个对象,如果是,则将其转换为该单个对象的数组。
以下是我要做的一些伪代码:
// Input
var obj = {
"records": {
"recordID": 1,
"recordName": 'test'
},
"photos": {
"photoID": 1,
"photoName": 'test flower'
},
"leaveMeAlone": {
"nopeID": 1,
"nopeName": 'tester'
}
}
function convertToArray(obj) {
var keysToArray = ['records', 'photos'];
// Loop over keys
for (var k in obj) {
// Properties
if (obj.hasOwnProperty(k)) {
// This key is in our array.
if (keysToArray.indexOf(k) > -1) {
// If this is a single object, turn it into an array containing a single object
if (!Array.isArray(obj[k])) {
// Turn this value into an array of the single object
/* Stuck Here */
}
}
}
}
/* Return
var obj = {
"records": [{
"recordID": 1,
"recordName": 'test'
}],
"photos": [{
"photoID": 1,
"photoName": 'test flower'
}],
"leaveMeAlone": {
"nopeID": 1,
"nopeName": 'tester'
}
}
*/
}
// run
convertToArray(obj);

答案 0 :(得分:2)
您可以使用我创建的以下方法。它将检查对象是否是数组。如果没有,则它会将对象放入数组中并返回。
function convertToArray(obj) {
if (obj.records instanceof Array) {
return obj.records;
} else {
return [obj.records];
}
}
JSFiddle https://jsfiddle.net/r4otdrq0/
答案 1 :(得分:1)
您可以通过将给定属性转换为数组(如果不是数组)来采用迭代和递归方法。
如果所有键都是唯一的,您可以通过删除数组的属性或更改从深度优先到广度优先搜索的路径来使用早期返回。
function convert(object, keys) {
Object.keys(object).forEach(function (k) {
if (object[k] && typeof object[k] === 'object') {
convert(object[k], keys);
}
if (keys.indexOf(k) !== -1 && !Array.isArray(object[k])) {
object[k] = [object[k]];
}
});
}
var object = { records: { recordID: 1, recordName: 'test' }, photos: { photoID: 1, photoName: 'test flower' }, leaveMeAlone: { nopeID: 1, nopeName: 'tester' }, nested: { convert: { foo: 1, bar: 2 } } },
keys = ['records', 'photos', 'convert'];
convert(object, keys);
console.log(object);

.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)
请注意,我已将内联值替换为内容,因此传入的对象会发生变异。除此之外,我希望它非常明显。
// Input
var obj = {
"records": {
"recordID": 1,
"recordName": 'test'
},
"photos": {
"photoID": 1,
"photoName": 'test flower'
},
"leaveMeAlone": {
"nopeID": 1,
"nopeName": 'tester'
}
}
function convertToArray(obj) {
var keysToArray = ['records', 'photos'];
keysToArray.forEach(function(key) {
if (key in obj && !Array.isArray(obj[key])) {
obj[key] = [obj[key]];
}
});
return obj;
}
console.log(convertToArray(obj));

根据您在下面的评论,您似乎需要在嵌套对象上执行此转换。下面是一个通过递归调用数组和对象来做到这一点的例子。请注意,它仅在决定是否转换为数组时检查键,而不关心用于到达那里的路径。只要您确定相同的键名不会用于具有不同期望的不同地方,这样就可以了:
function convertToArray(obj, keysToConvert) {
if (Array.isArray(obj)) {
obj.forEach(function(entry) {
convertToArray(entry, keysToConvert);
});
}
else if (obj && typeof obj === 'object') {
Object.keys(obj).forEach(function(key) {
if (keysToConvert.indexOf(key) !== -1 && !Array.isArray(obj[key])) {
obj[key] = [obj[key]];
}
convertToArray(obj[key], keysToConvert);
});
}
return obj;
}
var obj = {
"data": {
"VersionForTarget": "1",
"rules": {
"rule": {
"RuleParentID": "84",
"RuleVersionID": "2",
"MappedValue": "1",
"ProcessingOrder": "1",
"MetaInsertUtc": "2017-03-03T17:54:34.643",
"Value": "Recorded",
"IsRuleRetired": "0",
"UserImpactCount": "27130",
"attributes": {
"attribute": {
"AttributeID": "2",
"AttributeName": "Role",
"attributeDetails": {
"attributeDetail": [{
"RuleDetailID": "10964",
"AttributeID": "2",
"OperatorID": "3",
"AttributeValue": "172",
"RuleParentID": "84",
"Value": "Account Manager",
"IsValueRetired": "0",
"OperatorName": "In List",
"SqlOperator": "IN"
},
{
"RuleDetailID": "10966",
"AttributeID": "2",
"OperatorID": "3",
"AttributeValue": "686",
"RuleParentID": "84",
"Value": "Agent",
"IsValueRetired": "0",
"OperatorName": "In List",
"SqlOperator": "IN"
}
]
}
}
}
}
}
}
}
console.log(convertToArray(obj, ['rule', 'attribute', 'attributeDetail']))