Supprimer les attributs vides d'un objet en Javascript


Réponses:


184

Vous pouvez parcourir l'objet en boucle:

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);

Si vous ne souhaitez pas que cette suppression de propriété exécute la chaîne proptype de l'objet, vous pouvez également:

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

Quelques notes sur null vs indéfini:

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
Ajout d'une correction rapide. La variable "i" non déclarée fuirait dans la portée externe si cet extrait était jamais utilisé dans une fonction.
Eric Nguyen

4
vous pouvez simplifier le (test [i] === null || test [i] === undefined) en (test [i] == null)
jaf0

Salut, @EricNguyen, contrairement à C et à plusieurs autres langages, javascript n'a pas de portée de bloc pour les variables (seulement la portée de la fonction), ainsi, la variable i fuira toujours dans la portée après le bloc for .
Gerardo Lima

1
@GerardoLima, oui. Je supposais en quelque sorte que tout cela serait enveloppé dans une fonction. Ce que je voulais dire (en supposant que tout est enveloppé d'une fonction), c'est que vous avez besoin de la déclaration var ou je fuirai même en dehors de la portée de la fonction.
Eric Nguyen

Cela parcourra également le prototype de l'objet primitif - ce qui, dans la plupart des cas, n'est pas souhaité. stackoverflow.com/a/2869372/1612318
Rotareti

428

Utilisation de certains ES6 / ES2015 :

1) Une simple doublure pour retirer les articles en ligne sans affectation:

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

jsbin

2) Cet exemple a été supprimé ...

3) Premier exemple écrit en fonction:

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

jsbin

4) Cette fonction utilise également la récursivité pour supprimer les éléments des objets imbriqués:

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) Ceci est similaire au 4), mais au lieu de muter directement l'objet source, il renvoie un nouvel objet.

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) Une approche fonctionnelle de 4b) basée sur la réponse de @ MichaelJ.Zoidl en utilisant filter()et reduce(). Celui-ci renvoie également un nouvel objet:

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) Identique à 4) mais avec 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) Une autre version fonctionnelle qui utilise la récursivité et renvoie un nouvel objet avec 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) Identique à 4) mais en clair 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
@AugustinRiedinger Quand je dois choisir entre un saut de ligne et une abréviation, je choisis parfois l'abréviation si je pense que l'abréviation est le moindre mal. Le code en 5) n'est pas difficile à raisonner et c'est une fonction qui supprime le vide keysde an object, donc oet kest évident. Mais je suppose que c'est une question de goût.
Rotareti

3
Première version avec une saveur ES5:Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});
Neurotransmetteur

1
Une ligne, sans fonction:Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})
Paul Slm

7
Puisque nous essayons d'être approfondis, il pourrait être agréable de voir une solution immuable. Ceux-ci mutent l'objet source et retournent de manière trompeuse l'objet qui est en fait inutile parce que l'objet a été muté. Les débutants captureront la valeur d'objet retournée et se demanderont pourquoi leur objet source est également modifié.
Mike McLin

2
5) Ne fonctionne pas avec les tableaux (Object.keys renverra les numéros de position des tableaux comme clé pour les éléments). D'autres ont peut-être ce problème, mais je l'ai trouvé lors des tests 5.
Eelco

95

Si vous utilisez lodash ou underscore.js, voici une solution simple:

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

var compacted = _.pickBy(obj);

Cela ne fonctionnera qu'avec lodash 4, pre lodash 4 ou underscore.js, use _.pick(obj, _.identity);


1
Brillant! Je vous remercie! Pour info, ce qui n'était pas évident pour moi, c'est que vous pouviez l'utiliser aussi comme ceci: foo (). Then (_. PickBy); // filtrage des résultats vides
Maciej Gurban

29
Notez que cela n'aura pas le résultat souhaité si l'objet contient des valeurs fausses telles que 0 ou des chaînes vides. Alors _.omit(obj, _.isUndefined)c'est mieux.
JHH

5
@JHH _.isUndefinedn'omet pas de valeurs nulles, utilisez _.omitBy(obj, _.isNil)pour omettre les deux undefinedetnull
Lukasz Wiktor

@LukaszWiktor Correct, la question demandait undefined ou null.
JHH

88

Doublures les plus courtes pour ES6 +

Filtrer toutes les valeurs falsy ( "", 0, false, null, undefined)

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

Filtre nullet undefinedvaleurs:

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

Filtre UNIQUEMENT null

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

Filtre UNIQUEMENT undefined

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

Solutions récursives: filtresnull etundefined

Pour les objets:

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)), {});

Pour les objets et les tableaux:

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)), {});
  } 
}

10
Ce devrait être la seule réponse! Chacun de ces extraits générera un nouvel objet où l'ancien ne sera pas muté. C'est préférable! Une petite note si vous utilisez juste v == nullvous vérifierez contre undefinedet null.
Megajin

les cleanEmptysolutions récursives renverront un objet vide {}pour les objets Date
Emmanuel NK

Un peu plus de lisibilité dans les doublures simples les rendrait géniaux !!
zardilior

39

Si quelqu'un a besoin d'une version récursive de la réponse d'Owen (et d'Eric), la voici:

/**
 * 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);
        }
    }
}

Après le début de la boucle for, vous devez vérifier que l'objet hasOwnPropertyutiliseif(test.hasOwnProperty(i)) { ... }
Augie Gardner

@AugieGardner Je suis curieux de savoir pourquoi vous souhaitez vérifier cela - veuillez l'expliquer si vous le souhaitez. (Cela n'empêcherait-il pas la vérification des propriétés héritées?)
Wumms

24

JSON.stringify supprime les clés non définies.

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

Cela n'a pas fonctionné pour moi pour un objet profond, mais la réponse de Wumm ci - dessus l'a fait.
Suman

1
Si vous devez nullêtre traité comme undefinedutilisant la fonction de remplacement, pour plus d'informations, reportez-vous à cette réponse: stackoverflow.com/questions/286141/…
Hooman Askari

Sachez simplement que cela ne supprime pas les nullvaleurs. Essayez: let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }et ensuite console.log(removeUndefined(a)). Question était sur le point undefinedet les nullvaleurs.
mai

13

Vous recherchez probablement le deletemot - clé.

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

4
C'est ce qu'il fait ci-dessus, cela laisse également indéfini dans l'objet.
Josh Bedo

10

Solution Lodash la plus simple possible pour renvoyer un objet avec les valeurs nullet undefinedfiltrées.

_.omitBy(obj, _.isNil)


c'est la solution la plus propre à ce jour!
Jee Mok

9

Vous pouvez utiliser une combinaison de JSON.stringify, son paramètre de remplacement, et JSON.parsele transformer en objet. L'utilisation de cette méthode signifie également que le remplacement est effectué pour toutes les clés imbriquées dans les objets imbriqués.

Exemple d'objet

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

Fonction de remplacement

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

  return value;
}

Nettoyez l'objet

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

Exemple CodePen


6

En utilisant Ramda # pickBy vous enlèverez tous null, undefinedet les falsevaleurs:

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

Comme l'a souligné @manroe, pour conserver les falsevaleurs, utilisez isNil():

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

1
(v) => !R.isNil(v)est probablement un meilleur choix pour la question de OP, étant donné que falseou d'autres valeurs de fausseté seraient également rejetées parR.identity
manroe

6

Approche fonctionnelle et immuable, sans .filteret sans créer plus d'objets que nécessaire

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

Réponse très concise. Pour ajouter également la vérification nulle, remplacez simplement obj[key] === undefinedparobj[key] === undefined || obj[key] === null
user3658510

une légère variation de l'approche ci-dessus: vous pouvez également vous étendre conditionnellement dans la propriété obj véridique comme çaconst omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});
Kevin K.

6

Vous pouvez effectuer une suppression récursive sur une seule ligne à l'aide de l'argument de remplacement de json.stringify

const removeEmptyValues = obj => (
  JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)

Usage:

removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}

Comme mentionné dans le commentaire d'Emmanuel, cette technique ne fonctionnait que si votre structure de données ne contient que des types de données pouvant être mis au format JSON (chaînes, nombres, listes, etc.).

(Cette réponse a été mis à jour pour utiliser le nouvel opérateur Nullish Coalescing en fonction des besoins de soutien du navigateur que vous pouvez utiliser cette fonction au lieu. (k,v) => v!=null ? v : undefined)


1
cela convertir des objets en chaînes, date convertis NaNà nullqui ne sont pas supprimés.
Emmanuel NK

5

vous pouvez faire plus court avec !condition

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

Rappelez-vous à l'usage: comme @semicolor annonce dans les commentaires: Cela supprimerait également les propriétés si la valeur est une chaîne vide, fausse ou nulle


11
Cela supprimerait également les propriétés si la valeur est une chaîne vide, fausse ou nulle.
Point

3
C'était exactement ce que je cherchais pour supprimer les champs indésirables d'une demande JSON. Merci!
Phrozen

Utilisez [null, undefined].includes(r[k])au lieu de !r[k].
selmansamet

5

Solution ES6 pure plus courte, convertissez-la en tableau, utilisez la fonction de filtre et convertissez-la en objet. Serait aussi facile de faire une fonction ...

Btw. avec cela, .length > 0je vérifie s'il y a une chaîne / un tableau vide, donc il supprimera les clés vides.

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


1
Belle solution fonctionnelle
puiu

J'aime ça! Mais je pense que tout supprimer nullet undefinedqu'il serait plus simple de simplement l'utiliser MY_OBJECT[f] != null. Votre solution actuelle supprime tout sauf les chaînes / listes non vides et génère une erreur lorsque les valeurs sontnull
Rotareti

À droite, vous pouvez également utiliser / chaîne multiple filter, serait plus lisible.
Michael J.Zoidl

Si vous généralisez légèrement cela, je pense que vous vous rapprochez de ce que fait le loadash omit, vous devez vérifier que obj existe avant d'appeler Object.keys:const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});
icc97

Bien, mais toute valeur entière sera supprimée avec cette approche.
Ghis

4

Si vous voulez 4 lignes d'une solution ES7 pure:

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;

Ou si vous préférez une version plus lisible:

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

Cela préservera les valeurs booléennes et nettoiera également les tableaux. Il préserve également l'objet d'origine en renvoyant une copie nettoyée.


4

J'ai le même scénario dans mon projet et réalisé en utilisant la méthode suivante.

Il fonctionne avec tous les types de données, quelques-uns mentionnés ci-dessus ne fonctionnent pas avec la date et les tableaux vides.

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

passer n'importe quel objet à cette fonction removeEmptyKeysFromObject ()


4

Pour une recherche approfondie, j'ai utilisé le code suivant, peut-être qu'il sera utile pour quiconque regarde cette question (il n'est pas utilisable pour les dépendances cycliques):

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

3

Si vous ne voulez pas muter sur place, mais renvoyez un clone avec la valeur null / undefined supprimée, vous pouvez utiliser la fonction de réduction 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;
  }, {});
}

3

Au lieu de supprimer la propriété, vous pouvez également créer un nouvel objet avec les clés qui ne sont pas nulles.

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

3

Pour piggypack sur la réponse de Ben sur la façon de résoudre ce problème à l' aide de lodash _.pickBy, vous pouvez également résoudre ce problème dans la bibliothèque sœur: Underscore.js de _.pick.

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

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

Voir: Exemple JSFiddle


1
cela renvoie un tableau vide, vous avez également changé le nom de obj en objet
Stephen DuMont

Merci Stephen! Et maintenant? J'ai mis à jour ma réponse pour inclure un lien JSFiddle.
Alex Johnson

essayez d'utiliser _.omit (obj, _.isEmpty); c'est plus conceptuellement pur et inclura une chaîne vide.
Stephen DuMont

3

un assistant de réduction peut faire l'affaire (sans vérification de type) -

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

2

Si quelqu'un a besoin de supprimer des undefinedvaleurs d'un objet avec une recherche approfondie en utilisant lodashalors voici le code que j'utilise. Il est assez simple de le modifier pour supprimer toutes les valeurs vides ( 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;
  }, {});
}


1

Si vous utilisez eslint et que vous souhaitez éviter de déclencher la règle no-param-reusign, vous pouvez utiliser Object.assign en conjonction avec .reduce et un nom de propriété calculé pour une solution ES6 assez élégante:

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 }

1

Voici un moyen fonctionnel de supprimer nullsd'un objet à l'aide d'ES6 sans muter l'objet en utilisant uniquement reduce:

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

Commentaire de Troll Deux choses concernant le fait qu'il s'agit d'un modèle fonctionnel: au sein de la stripNullsfonction, il utilise une référence extérieure à la portée de la fonction accumulateur; et il mélange également les préoccupations en filtrant au sein de la fonction d'accumulateur. Eg (par exemple Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});) Oui, il fera une boucle sur les éléments filtrés deux fois, mais la perte de performance réalisée y est négligeable.
Jason Cust

1

Vous pouvez également utiliser la ...syntaxe étendue en utilisant forEachquelque chose comme ceci:

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);

1

Objet propre en place

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

cleanObj([undefined, null], obj)

Fonction pure

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)

Celui-ci est une belle solution, peut-être à une ligne
rekam

1

Nous pouvons utiliser JSON.stringify et JSON.parse pour supprimer les attributs vides d'un objet.

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

Cette astuce est en fait valide, tant que vous vous assurez que l'Obj est sérialisable en JSON. Et cela fonctionne aussi en profondeur.
Polv

Tableau et comparaison d'objets non valides ( {} != {}et [] != []), mais sinon l'approche est valide
Aivaras

1

Voici une fonction récursive complète (basée à l'origine sur celle de @chickens) qui:

  • supprimer récursivement ce que vous lui dites defaults=[undefined, null, '', NaN]
  • Manipulez correctement les objets, tableaux et objets Date normaux
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
}

USAGE:

// 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]))


0

Si vous préférez l'approche pure / fonctionnelle

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.