Как удалить все атрибуты undefined или null в объекте JavaScript?
(Вопрос аналогичен Вот этот для массивов)
Также здесь ES6 one liners без мутирующего объекта: stackoverflow.com/a/57625661/1602301



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете пройти по объекту в цикле:
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];
}
}
return obj
}
console.info(test);
console.info(clean(test));Если вас беспокоит, что удаление этого свойства не запускает цепочку типов свойств объекта, вы также можете:
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 и 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
Добавлено быстрое исправление. Необъявленная переменная "i" просочилась бы во внешнюю область видимости, если бы этот фрагмент кода когда-либо использовался в функции.
вы можете упростить (test [i] === null || test [i] === undefined) до (test [i] == null)
Привет, @EricNguyen, в отличие от C и других языков, в javascript нет есть область блока для переменных (только область действия), поэтому переменная яя> всегда будет попадать в область после блока для.
@GerardoLima, да. Я как бы предполагал, что все это будет заключено в функцию. Я имел в виду (при условии, что все это обернуто функцией), что вам нужно объявление var, иначе яя> будет протекать даже за пределами области действия функции.
Это также будет проходить через прототип примитивного объекта, что в большинстве случаев нежелательно. stackoverflow.com/a/2869372/1612318
@Rotareti только что обновил ответ, включив в него ответ, который ограничивается собственными свойствами объекта.
Не могли бы вы взглянуть на этот вопрос: stackoverflow.com/questions/42783607/…
плюс один для null vs undefined :)
можно сделать короче с условием !
var r = {a: null, b: undefined, c:1};
for(var k in r)
if (!r[k]) delete r[k];
Помните в использовании: как @semicolor анонсирует в комментариях: Это также приведет к удалению свойств, если значение является пустой строкой, ложью или нулем.
Это также приведет к удалению свойств, если значение является пустой строкой, ложью или нулем.
Это было именно то, что я искал, чтобы удалить ненужные поля из запроса JSON. Спасибо!
Используйте [null, undefined].includes(r[k]) вместо !r[k].
Если кому-то нужна рекурсивная версия ответа Оуэна (и Эрика), вот она:
/**
* 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);
}
}
}
После начала цикла for вы должны проверить, что объект hasOwnProperty с помощью if (test.hasOwnProperty(i)) { ... }
@AugieGardner Мне любопытно, почему вы хотите это проверить - пожалуйста, объясните, если хотите. (Разве это не помешало бы проверке унаследованных свойств?)
JSON.stringify удаляет неопределенные ключи.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
У меня это не сработало для глубокого объекта, но Ответ Вумма выше сработало.
Если вам нужно, чтобы null рассматривался как undefined, используйте функцию замены, для получения дополнительной информации обратитесь к этому ответу: stackoverflow.com/questions/286141/…
Просто имейте в виду, что это не удаляет значения null. Попробуйте: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }, а затем console.info(removeUndefined(a)). Вопрос касался значений undefined и null.
Методы JSON предназначены для строк json и никогда не должны использоваться для объектов javascript без надлежащего анализа и проверки.
Для глубокого поиска я использовал следующий код, возможно, он будет полезен для всех, кто задает этот вопрос (он не подходит для циклических зависимостей):
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;
}
Если вы используете lodash или underscore.js, вот простое решение:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
Это будет работать только с lodash 4, pre lodash 4 или underscore.js, используйте _.pick(obj, _.identity);
Блестяще! Спасибо! К вашему сведению, что для меня не было очевидным, так это то, что вы можете использовать его также так: foo (). Then (_. PickBy); // отфильтровываем пустые результаты
Обратите внимание, что это не приведет к желаемому результату, если объект содержит ложные значения, такие как 0 или пустые строки. Тогда лучше _.omit(obj, _.isUndefined).
@JHH _.isUndefined не пропускает нули, используйте _.omitBy(obj, _.isNil), чтобы опустить как undefined, так и null
@LukaszWiktor Правильно, в вопросе действительно задано значение undefined или null.
Чтобы скопировать на Ответ бена, как решить эту проблему с помощью lodash _.pickBy, вы также можете решить эту проблему в родственной библиотеке: Underscore.js's _.pick.
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
См .: Пример JSFiddle
это возвращает пустой массив, также вы изменили имя obj на объект
Спасибо, Стивен! Как насчет сейчас? Я обновил свой ответ, добавив ссылку на JSFiddle.
попробуйте использовать _.omit (obj, _.isEmpty); это более концептуально чисто и будет включать пустую строку.
Если кому-то нужно удалить значения 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;
}, {});
}
Простой однострочный (возврат нового объекта).
let o = Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));
То же, что и выше, но написано как функция.
function removeEmpty(obj) {
return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));
}
Эта функция использует рекурсия для удаления элементов из вложенных объектов.
function removeEmpty(obj) {
return Object.fromEntries(
Object.entries(obj)
.filter(([_, v]) => v != null)
.map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
);
}
Простой однострочный. Предупреждение: это изменяет данный объект вместо возврата нового.
Object.keys(obj).forEach((k) => obj[k] == null && delete obj[k]);
Одно объявление (не изменяющее данный объект).
let o = Object.keys(obj)
.filter((k) => obj[k] != null)
.reduce((a, k) => ({ ...a, [k]: obj[k] }), {});
То же, что и выше, но написано как функция.
function removeEmpty(obj) {
return Object.entries(obj)
.filter(([_, v]) => v != null)
.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
}
Эта функция использует рекурсию для удаления элементов из вложенных объектов.
function removeEmpty(obj) {
return Object.entries(obj)
.filter(([_, v]) => v != null)
.reduce(
(acc, [k, v]) => ({ ...acc, [k]: v === Object(v) ? removeEmpty(v) : v }),
{}
);
}
То же, что и функция выше, но написано в императивном (нефункциональном) стиле.
function removeEmpty(obj) {
const newObj = {};
Object.entries(obj).forEach(([k, v]) => {
if (v === Object(v)) {
newObj[k] = removeEmpty(v);
} else if (v != null) {
newObj[k] = obj[k];
}
});
return newObj;
}
Раньше все было намного многословнее.
Это нерекурсивная версия, написанная в функциональном стиле.
function removeEmpty(obj) {
return Object.keys(obj)
.filter(function (k) {
return obj[k] != null;
})
.reduce(function (acc, k) {
acc[k] = obj[k];
return acc;
}, {});
}
Это нерекурсивная версия, написанная в императивном стиле.
function removeEmpty(obj) {
const newObj = {};
Object.keys(obj).forEach(function (k) {
if (obj[k] && typeof obj[k] === "object") {
newObj[k] = removeEmpty(obj[k]);
} else if (obj[k] != null) {
newObj[k] = obj[k];
}
});
return newObj;
}
И рекурсивная версия, написанная в функциональном стиле.
function removeEmpty(obj) {
return Object.keys(obj)
.filter(function (k) {
return obj[k] != null;
})
.reduce(function (acc, k) {
acc[k] = typeof obj[k] === "object" ? removeEmpty(obj[k]) : obj[k];
return acc;
}, {});
}
Что касается №5, вы подразумеваете, что функциональный => нечитаемый? Зачем использовать o и k, когда в каждом другом примере вы используете object и key?
@AugustinRiedinger Когда мне приходится выбирать между переносом строки и сокращением, я иногда использую аббревиатуру, если считаю, что аббревиатура - меньшее зло. Код в 5) нетрудно понять, и это функция, которая удаляет пустой keys из object, поэтому o и k очевидны. Но думаю, это дело вкуса.
Первая версия с ароматом ES5: Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Одна линия, без функции: Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Я поддержал ваш ответ, но когда я увидел, что вы опускаете фигурные скобки, я действительно хотел отозвать мой голос: \
В # 6 val === null должен быть val == null (т.е. использовать оператор равенства вместо оператора идентичности). Аналогично, в №7 obj[key] === null должен быть obj[key] == null.
Мне это нравится, большое спасибо
Поскольку мы стараемся быть внимательными, было бы неплохо увидеть неизменное решение. Они изменяют исходный объект и обманчиво возвращают объект, который на самом деле не нужен, потому что объект был изменен. Новички будут фиксировать возвращаемое значение объекта и удивляться, почему их исходный объект тоже изменяется.
@MikeMcLin Хороший вопрос! 5) уже неизменен, но я добавил 4b), что является обязательным подходом к 5). Я также удалил оператор return из функций, изменяющих исходный объект. Теперь должно быть меньше путаницы. Я также удалил 2), так как это не имеет смысла.
Та же версия, что и 5), но короче:
Та же версия, что и 5), только короче: const removeEmpty = (obj) => return Object.keys (obj) .filter (k => obj [k]! == null && obj [k]! == undefined) // Удалить undefined и null .reduce ((newObj, k) => (newObj [k] = typeof obj [k] === 'object'? removeEmpty (obj [k]): obj [k], newObj), {}) ;
Как я могу удалить «отца», у которого больше есть атрибуты? например, у объекта все атрибуты были равны нулю, так в чем смысл сохранения объекта живым, я хочу удалить отца, если дочерние элементы больше не существуют, как я могу?
5) Не работает с массивами (Object.keys будет возвращать номера позиций массива в качестве ключа для элементов). Возможно, у других есть эта проблема, но я обнаружил это при тестировании 5.
Случай 4 работал у меня с небольшой модификацией условия else if (obj [key] == null || obj [key] == ''). Таким образом, я могу удалять элементы с пустыми строками (без символов и без пробелов).
Ухххх. Мне жаль, что я не копировал слепо одно из них. Я сходил с ума от DynamoDB. Пожалуйста, проверьте наличие Array.isArray(obj) перед typeof obj === 'object'. Array.isArray (obj) === true и typeof obj === 'object' пройдут.
Чем он лучше JSON.parse(JSON.stringify(obj, (k,v) => v==null?undefined:v)), упомянутого в stackoverflow.com/a/54707141/906265?
@Rotareti, почему я отменил предложение, которое я сделал, используя новую функцию для фрагмента кода, которая позволяет Stack правильно выполнять код javascript? Было ли это из-за использования console.info()? Я также исправил [7], потому что функция должна возвращать объект return obj;.
@Rotareti А что, когда есть только фигурные скобки {} ??? Например, JSON { g: {}, h: "test" }, который должен приводить к { h: "test" }
Вы можете использовать комбинацию JSON.stringify, его параметра replacer и 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]
}
]
};
Функция замены
function replaceUndefinedOrNull(key, value) {
if (value === null || value === undefined) {
return undefined;
}
return value;
}
Очистить объект
exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);
Для тех, кто использует машинописный текст или более новую версию node / js, это более короткая версия. const clean = (object: object) => JSON.parse(JSON.stringify(object, (_, value) => value ?? undefined));
Используя 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)
(v) => !R.isNil(v), вероятно, является лучшим выбором для вопроса OP, учитывая, что false или другие ложные значения также будут отклонены R.identityС Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
Это удалит также 0 или пустую строку '', лучше будет _.omitBy({a: 1, b: null, c: undefined, d: 0, e: ''}, (v) => typeof v !== undefined && typeof v !== 'null')
Если вы не хотите мутировать на месте, но возвращаете клон с удаленными значениями null / 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 removeEmpty = (obj) => {
return Object.keys(obj).filter(key => obj[key]).reduce(
(newObj, key) => {
newObj[key] = obj[key]
return newObj
}, {}
)
}
Более короткое чистое решение ES6, преобразовать его в массив, использовать функцию фильтрации и преобразовать обратно в объект. Также было бы легко сделать функцию ...
Кстати. с этим .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 BINhttps://jsbin.com/kugoyinora/edit?js,console
Хорошее функциональное решение
Мне это нравится! Но я думаю, что для удаления всех null и undefined было бы проще просто использовать MY_OBJECT[f] != null. Ваше текущее решение удаляет все, кроме непустых строк / списков, и выдает ошибку, когда значения равны null.
Правильно, вы также можете использовать / связать несколько filter, было бы более читабельно.
Если вы немного обобщите это, я думаю, вы приблизитесь к тому, что делает loadash omit, вам нужно проверить, существует ли obj, прежде чем вызывать Object.keys: const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
Хорошо, но при таком подходе любое целочисленное значение будет удалено.
Это работает для пустой объект? Ex JSON { f: 'te', a: [], b: {}, c: { c1: {} } }, который должен привести к { f: 'te' }
Простейшее возможное решение Lodash для возврата объекта с отфильтрованными значениями null и undefined.
_.omitBy(obj, _.isNil)
на данный момент это самое чистое решение!
Если вы используете 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 }
Если вам нужны 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;
}передать любой объект в эту функцию removeEmptyKeysFromObject ()
Вот функциональный способ удалить nulls из объекта с помощью ES6 без изменения объекта, используя только reduce:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
stripNulls он использует ссылку извне области действия функции аккумулятора; и он также смешивает проблемы, фильтруя в функции аккумулятора. ? (например, Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Да, он дважды перебирает отфильтрованные элементы, но реализованные потери производительности незначительны.// 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)
Это хорошее, возможно, однострочное решение
помощник reduce может сделать трюк (без проверки типов) -
const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
if (value) {
acc[key] = value;
}
return acc;
}, {});
Вы также можете использовать синтаксис ...spread, используя 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);
Если вы предпочитаете чистый / функциональный подход
const stripUndef = obj =>
Object.keys(obj)
.reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Если вы не хотите изменять исходный объект (используя некоторые операторы ES6):
const keys = Object.keys(objectWithNulls).filter(key => objectWithNulls[key]);
const pairs = keys.map(key => ({ [key]: objectWithNulls[key] }));
const objectWithoutNulls = pairs.reduce((val, acc) => ({ ...val, ...acc }));
filter(key => objectWithNulls[key]) возвращает все, что правда, поэтому отклоняет любые значения, такие как 0 или false, а также undefined или null. Может быть легко заменен на filter(key => objectWithNulls[key] !== undefined) или что-то подобное, если это нежелательное поведение.
Вы можете выполнить рекурсивное удаление в одной строке, используя Аргумент replacer json.stringify
const removeEmptyValues = obj => (
JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)
Использование:
removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}
Как упоминалось в комментарии Эммануэля, этот метод работал только в том случае, если ваша структура данных содержит только типы данных, которые могут быть помещены в формат JSON (строки, числа, списки и т. д.).
(Этот ответ был обновлен для использования нового Оператор Nullish Coalescing. В зависимости от потребностей поддержки браузера вы можете вместо этого использовать эту функцию: (k,v) => v!=null ? v : undefined)
это преобразует объекты Date в строки, преобразует NaN в null, которые не удаляются.
Рекурсивно удалять пустые, неопределенные, пустые объекты и пустые массивы, возвращая копию (версия ES6)
export function skipEmpties(dirty) {
let item;
if (Array.isArray(dirty)) {
item = dirty.map(x => skipEmpties(x)).filter(value => value !== undefined);
return item.length ? item : undefined;
} else if (dirty && typeof dirty === 'object') {
item = {};
Object.keys(dirty).forEach(key => {
const value = skipEmpties(dirty[key]);
if (value !== undefined) {
item[key] = value;
}
});
return Object.keys(item).length ? item : undefined;
} else {
return dirty === null ? undefined : dirty;
}
}
Функциональный и неизменный подход, без .filter и без создания большего количества объектов, чем необходимо
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
Очень лаконичный ответ. Чтобы также добавить нулевую проверку, просто замените obj[key] === undefined на obj[key] === undefined || obj[key] === null
небольшая вариация вышеупомянутого подхода: вы также можете условно распространить в истинном свойстве obj, например, const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Мы можем использовать JSON.stringify и JSON.parse для удаления пустых атрибутов из объекта.
jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
if (value == null || value == '' || value == [] || value == {})
return undefined;
return value;
});
Этот трюк действительно действителен, если вы убедитесь, что Obj сериализуем в формате JSON. И это тоже работает глубоко.
Неверное сравнение массивов и объектов ({} != {} и [] != []), но в остальном подход допустим.
Самый короткий лайнер для ES6 +
Отфильтровать все ложные значения ("", 0, false, null, undefined)
Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})
Отфильтруйте значения null и undefined:
Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})
ТОЛЬКО фильтр null
Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})
ТОЛЬКО фильтр undefined
Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})
Рекурсивные решения: Фильтры null и undefined
Для объектов:
const cleanEmpty = obj => Object.entries(obj)
.map(([k,v])=>[k,v && typeof v === "object" ? cleanEmpty(v) : v])
.reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});
Для объектов и массивов:
const cleanEmpty = obj => {
if (Array.isArray(obj)) {
return obj
.map(v => (v && typeof v === 'object') ? cleanEmpty(v) : v)
.filter(v => !(v == null));
} else {
return Object.entries(obj)
.map(([k, v]) => [k, v && typeof v === 'object' ? cleanEmpty(v) : v])
.reduce((a, [k, v]) => (v == null ? a : (a[k]=v, a)), {});
}
}
Это должен быть единственный ответ! Каждый из этих фрагментов будет генерировать новый объект, в котором старый не будет изменен. Это предпочтительнее! Небольшое примечание, если вы просто используете v == null, вы будете проверять его по undefined и null.
рекурсивные решения cleanEmpty вернут пустой объект {} для объектов Date.
Немного больше разборчивости в одинарных вкладышах сделало бы их потрясающими !!
Также хорошо работает с TypeScript. Object.entries (record) .reduce ((a: Anything, [k, v]) => (v.length! == 0? (A [k] = v, a): a), {}) где интерфейс Что-нибудь {[ключ: строка]: строка; }
Можно ли удалить из массивов только null, а не объекты ... как это изменить :). Пожалуйста помоги :)
Что вы имеете в виду @ GOXR3PLUS? удаление нулей из массивов так же просто, как arr = arr.filter(v=>v!==null)
@Superole Well i am trying to modify the above to remove the nulls only from the arrays inside the object. Поэтому я хочу, чтобы он касался только массивов внутри объекта и оставлял простые пары значений ключа нетронутыми, даже если значение равно нулю. Но если значение - массив [1,2,null,5,null], чтобы обрезать нули внутри массивов :)
@chickens а что насчет пустой объект? Пример: JSON { g: {}, h: "test" }, что приводит к { h: "test" }.
a, [k, v] => аккумулятор, ключ, значение
30+ ответов, но я не видел этого короткого однострочника ES6, использующего оператор распространения благодаря тому, что Object.assign() является функцией vararg, которая молча игнорирует любые не-объекты (например, false).
Object.assign({}, ...Object.entries(obj).map(([k,v]) => v != null && {[k]: v]))
Сбой во вложенной структуре: {1:{2:null}}
Если вы просто хотите удалить неопределенные свойства верхнего уровня из объекта, я считаю, что это самый простой вариант:
const someObject = {
a: null,
b: 'someString',
c: 3,
d: undefined
};
for (let [key, value] of Object.entries(someObject)) {
if (value === null || value === undefined) delete someObject[key];
}
console.info('Sanitized', someObject);ES6 arrow function and ternary operator:
Object.entries(obj).reduce((acc, entry) => {
const [key, value] = entry
if (value !== undefined) acc[key] = value;
return acc;
}, {})
const obj = {test:undefined, test1:1 ,test12:0, test123:false};
const newObj = Object.entries(obj).reduce((acc, entry) => {
const [key, value] = entry
if (value !== undefined) acc[key] = value;
return acc;
}, {})
console.info(newObj)
Вот комплексная рекурсивная функция (изначально основанная на функции @chickens), которая:
defaults=[undefined, null, '', NaN]const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
if (!defaults.length) return obj
if (defaults.includes(obj)) return
if (Array.isArray(obj))
return obj
.map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
.filter(v => !defaults.includes(v))
return Object.entries(obj).length
? Object.entries(obj)
.map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
.reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {})
: obj
}
ИСПОЛЬЗОВАНИЕ:
// based off the recursive cleanEmpty function by @chickens.
// This one can also handle Date objects correctly
// and has a defaults list for values you want stripped.
const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
if (!defaults.length) return obj
if (defaults.includes(obj)) return
if (Array.isArray(obj))
return obj
.map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
.filter(v => !defaults.includes(v))
return Object.entries(obj).length
? Object.entries(obj)
.map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
.reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {})
: obj
}
// testing
console.info('testing: undefined \n', cleanEmpty(undefined))
console.info('testing: null \n',cleanEmpty(null))
console.info('testing: NaN \n',cleanEmpty(NaN))
console.info('testing: empty string \n',cleanEmpty(''))
console.info('testing: empty array \n',cleanEmpty([]))
console.info('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.info('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.info('testing: comprehensive obj \n', cleanEmpty({
a: 5,
b: 0,
c: undefined,
d: {
e: null,
f: [{
a: undefined,
b: new Date(),
c: ''
}]
},
g: NaN,
h: null
}))
console.info('testing: different defaults \n', cleanEmpty({
a: 5,
b: 0,
c: undefined,
d: {
e: null,
f: [{
a: undefined,
b: '',
c: new Date()
}]
},
g: [0, 1, 2, 3, 4],
h: '',
}, [undefined, null]))удалить объект пустого поля
for (const objectKey of Object.keys(data)) {
if (data[objectKey] === null || data[objectKey] === '' || data[objectKey] === 'null' || data[objectKey] === undefined) {
delete data[objectKey];
}
}
На этот вопрос уже дан исчерпывающий ответ, я просто хотел бы поделиться своей версией на основе других приведенных примеров:
function filterObject(obj, filter) {
return Object.entries(obj)
.map(([key, value]) => {
return [key, value && typeof value === 'object'
? filterObject(value, filter)
: value];
})
.reduce((acc, [key, value]) => {
if (!filter.includes(value)) {
acc[key] = value;
}
return acc;
}, {});
}
Что отличает это решение, так это возможность указать, какие значения вы хотите фильтровать во втором параметре следующим образом:
const filtered = filterObject(originalObject, [null, '']);
Что вернет новый объект (не изменяет исходный объект), не включая свойства со значением null или ''.
Вот альтернатива
Машинопись:
function objectDefined <T>(obj: T): T {
const acc: Partial<T> = {};
for (const key in obj) {
if (obj[key] !== undefined) acc[key] = obj[key];
}
return acc as T;
}
Javascript:
function objectDefined(obj) {
const acc = {};
for (const key in obj) {
if (obj[key] !== undefined) acc[key] = obj[key];
}
return acc;
}
Если вас устраивает использование Лодаш, вы можете добавить рекурсивную библиотеку DeepDash и добиться желаемого с помощью довольно краткого кода:
const prune = obj => _.filterDeep(obj, (v) => !(_.isUndefined(v) || _.isNull(v)));
Вызов prune(anObjectWithNulls) вернет объект без значений undefined или null.
Удалите все свойства с null и undefined
let obj = {
"id": 1,
"firstName": null,
"lastName": null,
"address": undefined,
"role": "customer",
"photo": "fb79fd5d-06c9-4097-8fdc-6cebf73fab26/fc8efe82-2af4-4c81-bde7-8d2f9dd7994a.jpg",
"location": null,
"idNumber": null,
};
let result = Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});
console.info(result)
Настоятельно рекомендую людям игнорировать высший ранг и перейти к версиям ES6 / ES7 здесь, stackoverflow.com/a/38340730/124486