Wie entferne ich alle Attribute, die sind undefined oder nullin einem JavaScript - Objekt?
(Frage ist ähnlich wie diese für Arrays)
Wie entferne ich alle Attribute, die sind undefined oder nullin einem JavaScript - Objekt?
(Frage ist ähnlich wie diese für Arrays)
Antworten:
Sie können das Objekt durchlaufen:
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);
Wenn Sie befürchten, dass durch das Entfernen dieser Eigenschaft die Proptypkette des Objekts nicht ausgeführt wird, können Sie außerdem:
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];
}
}
}
Ein paar Anmerkungen zu 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
Verwendung von ES6 / ES2015 :
1) Ein einfacher Einzeiler zum Entfernen der Elemente inline ohne Zuordnung:
Object.keys(myObj).forEach((key) => (myObj[key] == null) && delete myObj[key]);
2) Dieses Beispiel wurde entfernt ...
3) Erstes Beispiel als Funktion geschrieben:
const removeEmpty = obj => {
Object.keys(obj).forEach(key => obj[key] == null && delete obj[key]);
};
4) Diese Funktion verwendet die Rekursion , um Elemente auch aus verschachtelten Objekten zu löschen:
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) Dies ist ähnlich wie 4), aber anstatt das Quellobjekt direkt zu mutieren, wird ein neues Objekt zurückgegeben.
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) Ein funktionaler Ansatz zu 4b) basierend auf der Antwort von @ MichaelJ.Zoidl unter Verwendung von filter()und reduce(). Dieser gibt auch ein neues Objekt zurück:
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) Wie 4), jedoch mit 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) Eine andere Funktionsversion
, die Rekursion verwendet und mit ES2019 ein neues Objekt zurückgibtObject.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) Wie 4), jedoch in einfachem 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]
});
};
keysaus einem entfernt object, also ound koffensichtlich ist. Aber ich denke, es ist Geschmackssache.
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; }, {})
Wenn Sie lodash oder underscore.js verwenden, ist hier eine einfache Lösung:
var obj = {name: 'John', age: null};
var compacted = _.pickBy(obj);
Dies funktioniert nur mit lodash 4, pre lodash 4 oder underscore.js _.pick(obj, _.identity).
_.omit(obj, _.isUndefined)ist es besser.
_.isUndefinedlässt keine Nullen aus, verwendet _.omitBy(obj, _.isNil)beide undefinedundnull
Kürzeste Einzeiler für ES6 +
Filter alle falsy Werte ( "", 0, false, null, undefined)
Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})
Filter nullund undefinedWerte:
Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})
NUR filtern null
Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})
NUR filtern undefined
Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})
Rekursive Lösungen: Filter nullundundefined
Für Objekte:
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)), {});
Für Objekte und Arrays:
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, werden Sie gegen undefinedund prüfen null.
cleanEmptyrekursiven Lösungen geben ein leeres Objekt {}für Datumsobjekte zurück
Wenn jemand eine rekursive Version von Owens (und Erics) Antwort benötigt, ist dies hier:
/**
* 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);
}
}
}
hasOwnPropertymitif(test.hasOwnProperty(i)) { ... }
JSON.stringify entfernt die undefinierten Schlüssel.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
nullals undefinedErsatzfunktion behandelt werden müssen , finden Sie weitere Informationen in dieser Antwort: stackoverflow.com/questions/286141/…
nullWerte entfernt werden. Versuchen Sie: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }und dann console.log(removeUndefined(a)). Frage war über undefinedund nullWerte.
Sie können eine Kombination aus JSON.stringifydem Ersetzungsparameter verwenden und JSON.parseihn wieder in ein Objekt verwandeln. Die Verwendung dieser Methode bedeutet auch, dass alle verschachtelten Schlüssel in verschachtelten Objekten ersetzt werden.
Beispielobjekt
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]
}
]
};
Ersatzfunktion
function replaceUndefinedOrNull(key, value) {
if (value === null || value === undefined) {
return undefined;
}
return value;
}
Reinigen Sie das Objekt
exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);
Mit Ramda # pickBy werden Sie alle entfernen null, undefinedund falseWerte:
const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)
Wie @manroe betonte, verwenden Sie, um falseWerte zu verwenden isNil():
const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
(v) => !R.isNil(v)ist wahrscheinlich eine bessere Wahl für die Frage von OP, da falseoder andere falsche Werte auch vonR.identity
Funktionaler und unveränderlicher Ansatz, ohne .filterund ohne mehr Objekte als nötig zu erstellen
Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
obj[key] === undefinedaufobj[key] === undefined || obj[key] === null
const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Sie können eine rekursive Entfernung in einer Zeile mit durchführen Ersetzerargument von json.stringify durchführen
const removeEmptyValues = obj => (
JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)
Verwendung:
removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}
Wie in Emmanuels Kommentar erwähnt, funktionierte diese Technik nur, wenn Ihre Datenstruktur nur Datentypen enthält, die in das JSON-Format (Zeichenfolgen, Zahlen, Listen usw.) gestellt werden können.
(Diese Antwort wurde die neuen zu verwenden , aktualisiert Nullish Coalescing Betreiber je nach Browser Support - Anforderungen können Sie diese Funktion nutzen , statt. (k,v) => v!=null ? v : undefined)
NaNin nulldie nicht konvertiert wird .
Sie können mit !Bedingung kürzer machen
var r = {a: null, b: undefined, c:1};
for(var k in r)
if(!r[k]) delete r[k];
Denken Sie bei der Verwendung daran: wie @semicolor in Kommentaren ankündigt: Dies würde auch Eigenschaften löschen, wenn der Wert eine leere Zeichenfolge, false oder null ist
[null, undefined].includes(r[k])anstelle von !r[k].
Kürzere reine ES6-Lösung, konvertieren Sie sie in ein Array, verwenden Sie die Filterfunktion und konvertieren Sie sie zurück in ein Objekt. Wäre auch einfach eine Funktion zu machen ...
Übrigens. Damit .length > 0überprüfe ich, ob es einen leeren String / Array gibt, damit leere Schlüssel entfernt werden.
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; }, {});
nullund undefinedes wäre einfacher, nur zu verwenden MY_OBJECT[f] != null. Ihre aktuelle Lösung entfernt alles außer nicht leeren Zeichenfolgen / Listen und null
filter, wäre besser lesbar.
omitmacht, müssen Sie überprüfen, ob obj existiert, bevor Sie anrufen Object.keys:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
Wenn Sie 4 Zeilen einer reinen ES7-Lösung wünschen:
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;
Oder wenn Sie eine besser lesbare Version bevorzugen:
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;
}
Dadurch bleiben boolesche Werte erhalten und Arrays werden bereinigt. Das Originalobjekt bleibt auch erhalten, indem eine bereinigte Kopie zurückgegeben wird.
Ich habe das gleiche Szenario in meinem Projekt und habe es mit der folgenden Methode erreicht.
Es funktioniert mit allen Datentypen, nur wenige der oben genannten funktionieren nicht mit Datums- und leeren Arrays.
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;
}
Übergeben Sie ein beliebiges Objekt an diese Funktion. removeEmptyKeysFromObject ()
Für eine gründliche Suche habe ich den folgenden Code verwendet. Vielleicht ist er für alle nützlich, die sich mit dieser Frage befassen (er kann nicht für zyklische Abhängigkeiten verwendet werden):
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;
}
Wenn Sie nicht an Ort und Stelle mutieren möchten, sondern einen Klon mit entferntem null / undefined zurückgeben möchten, können Sie die ES6-Reduktionsfunktion verwenden.
// 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;
}, {});
}
Um Bens Antwort auf die Lösung dieses Problems mit lodash's zu überprüfen _.pickBy, können Sie dieses Problem auch in der Schwesterbibliothek lösen: Underscore.js 's _.pick.
var obj = {name: 'John', age: null};
var compacted = _.pick(obj, function(value) {
return value !== null && value !== undefined;
});
Siehe: JSFiddle-Beispiel
Wenn jemand undefinedWerte aus einem Objekt mit Deep Search mit entfernen muss, lodashdann ist hier der Code, den ich verwende. Es ist ganz einfach, es zu ändern, um alle leeren Werte ( null/ undefined) zu entfernen .
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;
}, {});
}
Mit Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
Wenn Sie eslint verwenden und vermeiden möchten, dass die No-Param-Reignign-Regel ausgelöst wird, können Sie Object.assign in Verbindung mit .reduce und einem berechneten Eigenschaftsnamen für eine recht elegante ES6-Lösung verwenden:
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 }
Hier ist eine funktionale Möglichkeit, nullsmit ES6 aus einem Objekt zu entfernen , ohne das Objekt nur mit zu mutieren reduce:
const stripNulls = (obj) => {
return Object.keys(obj).reduce((acc, current) => {
if (obj[current] !== null) {
return { ...acc, [current]: obj[current] }
}
return acc
}, {})
}
stripNullsFunktion wird eine Referenz von außerhalb des Bereichs der Akkumulatorfunktion verwendet. und es mischt auch die Bedenken durch Filtern innerhalb der Akkumulatorfunktion. 😝 (zB Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Ja, die gefilterten Elemente werden zweimal
Sie können die ...Spread-Syntax auch folgendermaßen verwenden 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);
// 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)
Wir können JSON.stringify und JSON.parse verwenden, um leere Attribute aus einem Objekt zu entfernen.
jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
if (value == null || value == '' || value == [] || value == {})
return undefined;
return value;
});
{} != {}und [] != []), aber ansonsten ist der Ansatz gültig
Hier ist eine umfassende rekursive Funktion (ursprünglich basierend auf der von @chickens), die:
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
}
VERWENDUNG:
// 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.log('testing: undefined \n', cleanEmpty(undefined))
console.log('testing: null \n',cleanEmpty(null))
console.log('testing: NaN \n',cleanEmpty(NaN))
console.log('testing: empty string \n',cleanEmpty(''))
console.log('testing: empty array \n',cleanEmpty([]))
console.log('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.log('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.log('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.log('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]))
Wenn Sie den reinen / funktionalen Ansatz bevorzugen
const stripUndef = obj =>
Object.keys(obj)
.reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});