Удалить пустые атрибуты из объекта в Javascript

Как удалить все атрибуты, которые являются undefined или null в объекте JavaScript?

(Вопрос похож на этот для массивов)

Ответ 1

Вы можете прокручивать объект:

var test = {
    test1 : null,
    test2 : 'somestring',
    test3 : 3,
}

function clean(obj) {
  for (var propName in obj) { 
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
}

clean(test);

Если вы обеспокоены тем, что удаление этого свойства не запускает цепочку proptype объекта, вы также можете:

function clean(obj) {
  var propNames = Object.getOwnPropertyNames(obj);
  for (var i = 0; i < propNames.length; i++) {
    var propName = propNames[i];
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
}

Несколько заметок о null vs undefined:

test.test1 === null; // true
test.test1 == null; // true

test.notaprop === null; // false
test.notaprop == null; // true

test.notaprop === undefined; // true
test.notaprop == undefined; // true

Ответ 2

Используя некоторые ES6/ES2015:

1) Простой однострочник для удаления элементов в строке без присваивания:

Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);

jsbin

2) Этот пример был удален...

3) Первый пример, написанный как функция:

const removeEmpty = obj => {
  Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};

jsbin

4) Эта функция также использует рекурсию для удаления элементов из вложенных объектов:

const removeEmpty = obj => {
  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") removeEmpty(obj[key]); // recurse
    else if (obj[key] == null) delete obj[key]; // delete
  });
};

jsbin

4b) Это похоже на 4), но вместо непосредственного изменения исходного объекта он возвращает новый объект.

const removeEmpty = obj => {
  const newObj = {};

  Object.keys(obj).forEach(key => {
    if (obj[key] && typeof obj[key] === "object") {
      newObj[key] = removeEmpty(obj[key]); // recurse
    } else if (obj[key] != null) {
      newObj[key] = obj[key]; // copy value
    }
  });

  return newObj;
};

5) Функциональный подход к 4b) основан на ответе @MichaelJ.Zoidl с использованием filter() и reduce(). Этот также возвращает новый объект:

const removeEmpty = obj =>
  Object.keys(obj)
    .filter(k => obj[k] != null) // Remove undef. and null.
    .reduce(
      (newObj, k) =>
        typeof obj[k] === "object"
          ? { ...newObj, [k]: removeEmpty(obj[k]) } // Recurse.
          : { ...newObj, [k]: obj[k] }, // Copy value.
      {}
    );

jsbin

6) То же, что 4), но с ES7/2016 Object.entries().

const removeEmpty = (obj) => 
  Object.entries(obj).forEach(([key, val]) => {
    if (val && typeof val === 'object') removeEmpty(val)
    else if (val == null) delete obj[key]
})

5b) Другая функциональная версия, которая использует рекурсию и возвращает новый объект с ES2019 Object.fromEntries():

const removeEmpty = obj =>
  Object.fromEntries(
    Object.entries(obj)
      .filter(([k, v]) => v != null)
      .map(([k, v]) => (typeof v === "object" ? [k, removeEmpty(v)] : [k, v]))
  );

7) То же, что 4), но в простом ES5:

function removeEmpty(obj) {
  Object.keys(obj).forEach(function(key) {
    if (obj[key] && typeof obj[key] === 'object') removeEmpty(obj[key])
    else if (obj[key] == null) delete obj[key]
  });
};

jsbin

Ответ 3

Если вы используете lodash или underscore.js, вот простое решение:

var obj = {name: 'John', age: null};

var compacted = _.pickBy(obj);

Это будет работать только с lodash 4, pre lodash 4 или underscore.js, используйте _.pick(obj, _.identity);

Ответ 4

Если кому-то нужна рекурсивная версия ответа Оуэна (и Эрика), вот что:

/**
 * Delete all null (or undefined) properties from an object.
 * Set 'recurse' to true if you also want to delete properties in nested objects.
 */
function delete_null_properties(test, recurse) {
    for (var i in test) {
        if (test[i] === null) {
            delete test[i];
        } else if (recurse && typeof test[i] === 'object') {
            delete_null_properties(test[i], recurse);
        }
    }
}

Ответ 5

JSON.stringify удаляет ключи undefined.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}

Ответ 6

Возможно, вы ищете ключевое слово delete.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;

Ответ 7

Вы можете использовать комбинацию JSON.stringify, ее параметр замены и JSON.parse, чтобы вернуть ее обратно в объект. Использование этого метода также означает, что замена выполняется для всех вложенных ключей внутри вложенных объектов.

Пример объекта

var exampleObject = {
  string: 'value',
  emptyString: '',
  integer: 0,
  nullValue: null,
  array: [1, 2, 3],
  object: {
    string: 'value',
    emptyString: '',
    integer: 0,
    nullValue: null,
    array: [1, 2, 3]
  },
  arrayOfObjects: [
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    },
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    }
  ]
};

Функция Replacer

function replaceUndefinedOrNull(key, value) {
  if (value === null || value === undefined) {
    return undefined;
  }

  return value;
}

Очистить объект

exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);

Пример CodePen

Ответ 8

Простейшее возможное решение Lodash для возврата объекта с отфильтрованными значениями null и undefined.

_.omitBy(obj, _.isNil)

Ответ 9

Самый короткий вкладыш для ES6+

Отфильтровать все ложные значения ("", 0, false, null, undefined)

Object.entries(obj).reduce((a,[k,v]) => (v ? {...a, [k]:v} : a), {})

Фильтр только ноль

Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : {...a, [k]:v}), {})

Фильтр ТОЛЬКО неопределенный

Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : {...a, [k]:v}), {})

Фильтр неопределенных и нулевых значений:

Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : {...a, [k]:v}), {})

Ответ 10

Используя ramda # pickBy, вы удалите все null, undefined и false значения:

const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)

Как указал @manroe, для сохранения false значений используйте isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)

Ответ 11

Короче чистое решение ES6, конвертируйте его в массив, используйте функцию фильтра и конвертируйте его обратно в объект. Также было бы легко сделать функцию...

Btw. при этом .length > 0 я проверяю, есть ли пустая строка/массив, поэтому он удалит пустые ключи.

const MY_OBJECT = { f: 'te', a: [] }

Object.keys(MY_OBJECT)
 .filter(f => !!MY_OBJECT[f] && MY_OBJECT[f].length > 0)
 .reduce((r, i) => { r[i] = MY_OBJECT[i]; return r; }, {});

JS BIN https://jsbin.com/kugoyinora/edit?js,console

Ответ 12

Функциональный и неизменный подход, без .filter и без создания большего количества объектов, чем необходимо

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})

Ответ 13

Если вы хотите 4 строки чистого решения ES7:

const clean = e => e instanceof Object ? Object.entries(e).reduce((o, [k, v]) => {
  if (typeof v === 'boolean' || v) o[k] = clean(v);
  return o;
}, e instanceof Array ? [] : {}) : e;

Или, если вы предпочитаете более читаемую версию:

function filterEmpty(obj, [key, val]) {
  if (typeof val === 'boolean' || val) {
    obj[key] = clean(val)
  };

  return obj;
}

function clean(entry) {
  if (entry instanceof Object) {
    const type = entry instanceof Array ? [] : {};
    const entries = Object.entries(entry);

    return entries.reduce(filterEmpty, type);
  }

  return entry;
}

Это сохранит логические значения, и он также очистит массивы. Он также сохраняет исходный объект, возвращая очищенную копию.

Ответ 14

У меня такой же сценарий в моем проекте, и он был реализован следующим образом.

Он работает со всеми типами данных, немногие из упомянутых выше не работают с датой и пустыми массивами.

removeEmptyKeysFromObject.js

removeEmptyKeysFromObject(obj) {
   Object.keys(obj).forEach(key => {
  if (Object.prototype.toString.call(obj[key]) === '[object Date]' && (obj[key].toString().length === 0 || obj[key].toString() === 'Invalid Date')) {
    delete obj[key];
  } else if (obj[key] && typeof obj[key] === 'object') {
    this.removeEmptyKeysFromObject(obj[key]);
  } else if (obj[key] == null || obj[key] === '') {
    delete obj[key];
  }

  if (obj[key]
    && typeof obj[key] === 'object'
    && Object.keys(obj[key]).length === 0
    && Object.prototype.toString.call(obj[key]) !== '[object Date]') {
    delete obj[key];
  }
});
  return obj;
}

Ответ 15

вы можете сделать короче с условием !

var r = {a: null, b: undefined, c:1};
for(var k in r)
   if(!r[k]) delete r[k];

Помните об использовании: как @semicolor объявить в комментариях: это также приведет к удалению свойств, если значение представляет собой пустую строку, false или zero

Ответ 16

Для глубокого поиска я использовал следующий код, может быть, он будет полезен всем, кто смотрит на этот вопрос (его нельзя использовать для циклических зависимостей):

function removeEmptyValues(obj) {
        for (var propName in obj) {
            if (!obj[propName] || obj[propName].length === 0) {
                delete obj[propName];
            } else if (typeof obj[propName] === 'object') {
                removeEmptyValues(obj[propName]);
            }
        }
        return obj;
    }

Ответ 17

Чтобы скомпоновать ответ Ben о том, как решить эту проблему, используя lodash _.pickBy, вы также можете решить эту проблему в сестринской библиотеке: Underscore.js _.pick.

var obj = {name: 'John', age: null};

var compacted = _.pick(obj, function(value) {
  return value !== null && value !== undefined;
});

Смотрите: Пример JSFiddle

Ответ 18

Если вы не хотите мутировать на месте, но верните клон с нулевым / undefined удаленным, вы можете использовать функцию сокращения ES6.

// Helper to remove undefined or null properties from an object
function removeEmpty(obj) {
  // Protect against null/undefined object passed in
  return Object.keys(obj || {}).reduce((x, k) => {
    // Check for null or undefined
    if (obj[k] != null) {
      x[k] = obj[k];
    }
    return x;
  }, {});
}

Ответ 19

помощник сокращения может сделать трюк (без проверки типа) -

const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
      if (value) {
        acc[key] = value;
      }
      return acc;
    }, {});

Ответ 20

Если кому-то нужно удалить значения undefined из объекта с глубоким поиском, используя lodash, то вот код, который я использую. Это довольно просто изменить, чтобы удалить все пустые значения (null/undefined).

function omitUndefinedDeep(obj) {
  return _.reduce(obj, function(result, value, key) {
    if (_.isObject(value)) {
      result[key] = omitUndefinedDeep(value);
    }
    else if (!_.isUndefined(value)) {
      result[key] = value;
    }
    return result;
  }, {});
}

Ответ 21

Вместо удаления свойства вы также можете создать новый объект с ключами, которые не являются нулевыми.

const removeEmpty = (obj) => {
  return Object.keys(obj).filter(key => obj[key]).reduce(
    (newObj, key) => {
      newObj[key] = obj[key]
      return newObj
    }, {}
  )
}

Ответ 22

Если вы используете eslint и хотите избежать отключения правила no-param-reassign, вы можете использовать Object.assign в сочетании с .reduce и вычисленным именем свойства для довольно элегантного решения ES6:

const queryParams = { a: 'a', b: 'b', c: 'c', d: undefined, e: null, f: '', g: 0 };
const cleanParams = Object.keys(queryParams) 
  .filter(key => queryParams[key] != null)
  .reduce((acc, key) => Object.assign(acc, { [key]: queryParams[key] }), {});
// { a: 'a', b: 'b', c: 'c', f: '', g: 0 }

Ответ 23

Вот это функциональный способ удаления nulls из объекта с использованием ES6 без мутирует объект с использованием только reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}

Ответ 24

Очистить объект на месте

// General cleanObj function
const cleanObj = (valsToRemoveArr, obj) => {
   Object.keys(obj).forEach( (key) =>
      if (valsToRemoveArr.includes(obj[key])){
         delete obj[key]
      }
   })
}

cleanObj([undefined, null], obj)

Чистая функция

const getObjWithoutVals = (dontReturnValsArr, obj) => {
    const cleanObj = {}
    Object.entries(obj).forEach( ([key, val]) => {
        if(!dontReturnValsArr.includes(val)){
            cleanObj[key]= val
        } 
    })
    return cleanObj
}

//To get a new object without 'null' or 'undefined' run: 
const nonEmptyObj = getObjWithoutVals([undefined, null], obj)

Ответ 25

Вы также можете использовать ... распространять синтаксис, используя forEach что-то вроде этого:

let obj = { a: 1, b: "b", c: undefined, d: null };
let cleanObj = {};

Object.keys(obj).forEach(val => {
  const newVal = obj[val];
  cleanObj = newVal ? { ...cleanObj, [val]: newVal } : cleanObj;
});

console.info(cleanObj);

Ответ 26

Эта функция может очистить пустой объект после удаления invidival emptys внутри объекта или массива. это гарантирует, что у вас нет пустого массива или объекта, висящего вокруг.

function removeNullsInObject(obj) {
            if( typeof obj === 'string' || obj === "" ){
                return;
            }
            $.each(obj, function(key, value){
                if (value === "" || value === null){
                    delete obj[key];
                } else if ($.isArray(value)) {
                    if( value.length === 0 ){
                        delete obj[key];
                        return;
                    }
                    $.each(value, function (k,v) {
                        removeNullsInObject(v);
                    });
                    if( value.length === 0 ){
                        delete obj[key];
                    }
                } else if (typeof value === 'object') {
                    if( Object.keys(value).length === 0 ){
                        delete obj[key];
                        return;
                    }
                    removeNullsInObject(value);
                    if( Object.keys(value).length === 0 ){
                        delete obj[key];
                    }
                }
            });
 }

Ответ 27

Ниже решения удаляется null, а также empty object
empty object или {} является остаточным из-за null очистки

Чтобы очистить объект, используйте ниже

/**
 * Delete all null (or undefined) properties from an object.
 * Set 'recurse' to true if you also want to delete properties in nested objects.
 */
function delete_null_properties(test, recurse) {
  for (var i in test) {
    if (test[i] === null || test[i] === undefined) {
      delete test[i];
    }
    // recurse for array and object
    else if (recurse && typeof test[i] === 'object') {
      test[i] = delete_null_properties(test[i], recurse);
    }
    if((test[i] && typeof(test[i]) === 'object') && 
      (Object.keys(test[i]).length === 0 || test[i] == [{}])) {
      // delete the child property if its empty
      delete test[i]
    }
    if(test == {}){
      // delete empty 'parent' object when there is a residue due to deletion
      // of its child properties
      delete test
    } else if(test instanceof Array && test[i] == undefined) {
      // in the case of array removed null childs by splicing it off
      test.splice(i,1)
      // however if the parent array itself goes empty remove it off
      if(test instanceof Array && test.length == 0) {
        test = null
      }
    }    
  }
  return test
}

delete_null_properties(obj, true)

Ответ 28

С Lodash:

_.omitBy({a: 1, b: null}, (v) => !v)

Ответ 29

Вы можете использовать этот объект-чистый компонент, чтобы очистить все свойства фальши объекта и вернуть новый объект без них.

Примеры:

new cleaned object

 clean({ foo: null, bar: 'foo' }) // => { bar: 'foo' }

Ответ 30

const sampleObj = { 
  prop1: 1,
  prop2:'foo',
  prop3: '',
  prop4: null,
  prop5: undefined,

  };

const filterNullValue = (sampleObj) => {
  let resultObj = {};
  Object.keys(sampleObj).map((propertyKey) => {

    if (sampleObj[propertyKey]) { 
      resultObj[propertyKey] = sampleObj[propertyKey]; 
    }
  });
  return resultObj;
};
console.log(filterNullValue(sampleObj));