Как удалить все атрибуты, которые являются undefined
или null
в объекте JavaScript?
(Вопрос похож на этот для массивов)
Как удалить все атрибуты, которые являются undefined
или null
в объекте JavaScript?
(Вопрос похож на этот для массивов)
Вы можете прокручивать объект:
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
Используя некоторые ES6/ES2015:
1) Простой однострочник для удаления элементов в строке без присваивания:
Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);
2) Этот пример был удален...
3) Первый пример, написанный как функция:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};
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
});
};
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.
{}
);
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]
});
};
Если вы используете lodash или underscore.js, вот простое решение:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
Это будет работать только с lodash 4, pre lodash 4 или underscore.js, используйте _.pick(obj, _.identity)
;
Если кому-то нужна рекурсивная версия ответа Оуэна (и Эрика), вот что:
/**
* 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);
}
}
}
JSON.stringify удаляет ключи undefined.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
Возможно, вы ищете ключевое слово delete
.
var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
Вы можете использовать комбинацию 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);
Простейшее возможное решение Lodash для возврата объекта с отфильтрованными значениями null
и undefined
.
_.omitBy(obj, _.isNil)
Самый короткий вкладыш для 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}), {})
Используя 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)
Короче чистое решение 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; }, {});
Функциональный и неизменный подход, без .filter
и без создания большего количества объектов, чем необходимо
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
Если вы хотите 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;
}
Это сохранит логические значения, и он также очистит массивы. Он также сохраняет исходный объект, возвращая очищенную копию.
У меня такой же сценарий в моем проекте, и он был реализован следующим образом.
Он работает со всеми типами данных, немногие из упомянутых выше не работают с датой и пустыми массивами.
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;
}
вы можете сделать короче с условием !
var r = {a: null, b: undefined, c:1};
for(var k in r)
if(!r[k]) delete r[k];
Помните об использовании: как @semicolor объявить в комментариях: это также приведет к удалению свойств, если значение представляет собой пустую строку, false или zero
Для глубокого поиска я использовал следующий код, может быть, он будет полезен всем, кто смотрит на этот вопрос (его нельзя использовать для циклических зависимостей):
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;
}
Чтобы скомпоновать ответ Ben о том, как решить эту проблему, используя lodash _.pickBy
, вы также можете решить эту проблему в сестринской библиотеке: Underscore.js _.pick
.
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
Смотрите: Пример JSFiddle
Если вы не хотите мутировать на месте, но верните клон с нулевым / 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;
}, {});
}
помощник сокращения может сделать трюк (без проверки типа) -
const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
if (value) {
acc[key] = value;
}
return acc;
}, {});
Если кому-то нужно удалить значения 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;
}, {});
}
Вместо удаления свойства вы также можете создать новый объект с ключами, которые не являются нулевыми.
const removeEmpty = (obj) => {
return Object.keys(obj).filter(key => obj[key]).reduce(
(newObj, key) => {
newObj[key] = obj[key]
return newObj
}, {}
)
}
Если вы используете 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 }
Вот это функциональный способ удаления nulls
из объекта с использованием ES6 без мутирует объект с использованием только reduce
:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
// 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)
Вы также можете использовать ...
распространять синтаксис, используя 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);
Эта функция может очистить пустой объект после удаления 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];
}
}
});
}
Ниже решения удаляется 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)
С Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
Вы можете использовать этот объект-чистый компонент, чтобы очистить все свойства фальши объекта и вернуть новый объект без них.
Примеры:
new cleaned object
clean({ foo: null, bar: 'foo' }) // => { bar: 'foo' }
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));