2013-08-29 123 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; 
}