2013-08-29 90 views
18

我有一个JSON obj,在一些操作(如删除一些作品)后,我打印它,除了我有一些null值之外,一切看起来都不错。我如何删除这些?从JavaScript对象递归删除空值

我用JSON.stringify(obj, null, 2)方法来打印,这里是什么样子:

{ 
    "store": { 
     "book": [ 
      null, 
      { 
       "category": "fiction", 
       "author": "Evelyn Waugh", 
       "title": "Sword of Honour", 
       "price": 12.99 
      }, 
      null, 
      { 
        "category": "fiction", 
        "author": "J. R. R. Tolkien", 
        "title": "The Lord of the Rings", 
        "isbn": "0-395-19395-8", 
        "price": 22.99 
      } 
     ], 
     "bicycle": { 
      "color": "red", 
      null, 
      "price": 19.95 
     } 
    } 
} 

我想这是很多紧凑,很干净(删除多余的3个null值):

{ 
    "store": { 
     "book": [ 
      { 
       "category": "fiction", 
       "author": "Evelyn Waugh", 
       "title": "Sword of Honour", 
       "price": 12.99 
      }, 
      { 
        "category": "fiction", 
        "author": "J. R. R. Tolkien", 
        "title": "The Lord of the Rings", 
        "isbn": "0-395-19395-8", 
        "price": 22.99 
      } 
     ], 
     "bicycle": { 
      "color": "red", 
      "price": 19.95 
     } 
    } 
} 
+5

你'bicycle'是无效的语法,因为'null'的。 –

+1

我想知道'JSON.stringify'的哪个实现产生了无效的JSON。 –

+0

忽略自行车元素,你就在这里,这是我的错误 – lauxp

回答

4

固定您的book数组很容易 - 您只需要过滤出空值。最直接的方法很可能会建立一个新的数组,并重新分配它:

var temp = []; 
var i; 
for (i = 0; i < obj.store.book.length; ++i) { 
    if (obj.store.book[i] != null) { 
     temp.push(obj.store.book[i]); 
    } 
} 
obj.store.book = temp; 

我敢肯定有很多其他的方法,比如使用jQuery或filter功能(我相信是不能在较早的可用浏览器)。您也可以循环遍历数组,并从空值中取出splice。我只是觉得这种方式最容易阅读。

0

我在这里使用

Remove empty elements from an array in Javascript

那么代码,你可以这样调用它

JSON.stringify(obj.clean(空),空,2)

您需要修改代码以使用对象(或者在对象内部使用代码)

+0

if obj不是数组,没有干净错误的方法.. – lauxp

+0

是的,这就是为什么我说要么修改或运行它的对象内 – exussum

1

你如何删除你的作品?

使用delete操作符在阵列中留下一个孔来删除数组元素。 相反,你应该使用Array.splice这可以正确地从数组中删除一个元素。

10
// Iterate the array from back to front, removing null entries 
for (var i=obj.store.book.length;i--;){ 
    if (obj.store.book[i]===null) obj.store.book.splice(i,1); 
} 

如果你想从对象和数组递归删除所有null值:

// Compact arrays with null entries; delete keys from objects with null value 
function removeNulls(obj){ 
    var isArray = obj instanceof Array; 
    for (var k in obj){ 
    if (obj[k]===null) isArray ? obj.splice(k,1) : delete obj[k]; 
    else if (typeof obj[k]=="object") removeNulls(obj[k]); 
    } 
} 

在行动中看到:

var o = { 
    "store": { 
    "book": [ 
     null, 
     { 
     "category": "fiction", 
     "author": "Evelyn Waugh", 
     "title": "Sword of Honour", 
     "price": 12.99 
     }, 
     null, 
     { 
      "category": "fiction", 
      "author": "J. R. R. Tolkien", 
      "title": "The Lord of the Rings", 
      "isbn": "0-395-19395-8", 
      "price": 22.99 
     } 
    ], 
    "bicycle": { 
     "color": "red", 
     "bad": null, 
     "price": 19.95 
    } 
    } 
} 

removeNulls(o); 

console.log(JSON.stringify(o,null,2)); 
// { 
// "store": { 
//  "book": [ 
//  { 
//   "category": "fiction", 
//   "author": "Evelyn Waugh", 
//   "title": "Sword of Honour", 
//   "price": 12.99 
//  }, 
//  { 
//   "category": "fiction", 
//   "author": "J. R. R. Tolkien", 
//   "title": "The Lord of the Rings", 
//   "isbn": "0-395-19395-8", 
//   "price": 22.99 
//  } 
//  ], 
//  "bicycle": { 
//  "color": "red", 
//  "price": 19.95 
//  } 
// } 
// } 
+0

如何递归迭代一个对象来应用这个例程?考虑我不知道对象的结构,store.book只是我写在这里的一个例子..我是一个新的Javascript家伙 – lauxp

+0

我已经添加了一个实现,将递归爬取对象/数组,并删除'空值“。 – Phrogz

+0

谢谢,不知道为什么它永远不会落入这个'if'分支:if(obj [k] === null),hm .. – lauxp

33

我不得不解决类似的问题,但是我想要删除不仅值,而且undefined,的NaN空String空数组空对象值,递归地,通过检查嵌套对象和也嵌套阵列。

下面的函数使用罗短跑:

function pruneEmpty(obj) { 
    return function prune(current) { 
    _.forOwn(current, function (value, key) { 
     if (_.isUndefined(value) || _.isNull(value) || _.isNaN(value) || 
     (_.isString(value) && _.isEmpty(value)) || 
     (_.isObject(value) && _.isEmpty(prune(value)))) { 

     delete current[key]; 
     } 
    }); 
    // remove any leftover undefined values from the delete 
    // operation on an array 
    if (_.isArray(current)) _.pull(current, undefined); 

    return current; 

    }(_.cloneDeep(obj)); // Do not modify the original object, create a clone instead 
} 

例如,如果你用下面的输入对象调用的方法:

var dirty = { 
    key1: 'AAA', 
    key2: { 
    key21: 'BBB' 
    }, 
    key3: { 
    key31: true, 
    key32: false 
    }, 
    key4: { 
    key41: undefined, 
    key42: null, 
    key43: [], 
    key44: {}, 
    key45: { 
     key451: NaN, 
     key452: { 
     key4521: {} 
     }, 
     key453: [ {foo: {}, bar:''}, NaN, null, undefined ] 
    }, 
    key46: '' 
    }, 
    key5: { 
    key51: 1, 
    key52: ' ', 
    key53: [1, '2', {}, []], 
    key54: [{ foo: { bar: true, baz: null }}, { foo: { bar: '', baz: 0 }}] 
    }, 
    key6: function() {} 
}; 

它会递归地放弃所有的“坏“价值观,只保留那些带有一些信息的价值观。

var clean = pruneEmpty(dirty); 
console.log(JSON.stringify(clean, null, 2)); 

{ 
    key1: 'AAA', 
    key2: { 
    key21: 'BBB' 
    }, 
    key3: { 
    key31: true, 
    key32: false 
    }, 
    key5: { 
    key51: 1, 
    key52: ' ', 
    key53: [1, '2'], 
    key54: [{ foo: { bar: true }}, { foo: { baz: 0 }}] 
    } 
}; 

希望它有帮助!

+1

最好的答案之一...(y) –

2

以下是@Phrogz对答案的修改。如果book [3]也为null,则给出的答案不会删除最后一个null,因为在上一次循环的迭代中,数组的长度将小于k。

下面将通过执行到阵列的第二个呼叫工作:

function removeNulls(obj) { 
    var isArray = obj instanceof Array; 
    for (var k in obj) { 
    if (obj[k] === null) isArray ? obj.splice(k, 1) : delete obj[k]; 
    else if (typeof obj[k] == "object") removeNulls(obj[k]); 
    if (isArray && obj.length == k) removeNulls(obj); 
    } 
    return obj; 
}