Подтвердить что ты не робот

Рекурсивно удалить нулевые значения из объекта JavaScript

У меня есть JSON obj, после некоторых операций (например, удаление некоторых частей) я печатаю его, и все выглядит хорошо, за исключением того, что у меня есть значения null. Как удалить их?

Я использую метод 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
        }
    }
}
4b9b3361

Ответ 1

Мне пришлось решить аналогичную проблему, однако мне хотелось удалить не только значения null, но также undefined, NaN, пустой String, пустой массив и пустой объект, проверяя вложенные объекты, а также вложенные массивы.

Следующая функция использует Lo-Dash:

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 }}]
  }
};

Надеюсь, что это поможет!

Ответ 2

// 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
//     }
//   }
// }

Ответ 3

Исправление массива 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 из нулей. Я просто нахожу этот способ самым легким для чтения.

Ответ 4

Ниже приведена модификация ответа от @Phrogz. Если книга [3] также была нулевой, ответ не удалял последний нуль, потому что длина массива была бы меньше 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;
}

Ответ 5

Как вы удаляете свои фрагменты?

Удаление элемента массива с помощью оператора delete оставляет отверстие в массиве. Вместо этого вы должны использовать Array.splice, который может корректно удалить элемент из массива.

Ответ 6

Пожалуйста, используйте этот пакет npm

npm i --save nnjson
var nnjson = require('nnjson');
user = {
  a: null,
  b: 'hello',
  c: {
    c1: 'world',
    c2: null
  }
}
var newUser = nnjson.removeNull(user);
console.log (newUser)

результат

{
  b: 'hello',
  c: {
    c1: 'world'
  }
}

Ответ 7

Я использую здесь код

Удалить пустые элементы из массива в Javascript

тогда вы можете называть его как

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

Вам нужно будет изменить код для работы с объектами (или использовать код как внутри объектов)

Ответ 8

Мы можем использовать JSON.stringify и JSON.parse вместе для рекурсивного удаления пустых атрибутов из объекта.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });