2010-11-23 15 views
8

Je suis en train de sérialiser plusieurs dictionnaires imbriqués dans JSON en utilisant Python avec simplejson.Exclure les valeurs vides/NULL de la sérialisation JSON

Existe-t-il un moyen d'exclure automatiquement les valeurs vides/nulles?

Par exemple, sérialiser:

{ 
    "dict1" : { 
    "key1" : "value1", 
    "key2" : None 
    } 
} 

à

{ 
    "dict1" : { 
    "key1" : "value1" 
    } 
} 

Lorsque vous utilisez Jackson avec Java, vous pouvez utiliser Inclusion.NON_NULL pour ce faire. Y a-t-il un équivalent simplejson?

Répondre

11
def del_none(d): 
    """ 
    Delete keys with the value ``None`` in a dictionary, recursively. 

    This alters the input so you may wish to ``copy`` the dict first. 
    """ 
    # For Python 3, write `list(d.items())`; `d.items()` won’t work 
    # For Python 2, write `d.items()`; `d.iteritems()` won’t work 
    for key, value in list(d.items()): 
     if value is None: 
      del d[key] 
     elif isinstance(value, dict): 
      del_none(value) 
    return d # For convenience 

Exemple d'utilisation:

>>> mydict = {'dict1': {'key1': 'value1', 'key2': None}} 
>>> print(del_none(mydict.copy())) 
{'dict1': {'key1': 'value1'}} 

Ensuite, vous pouvez nourrir que de json.

+0

Em .... Cela produit 'RuntimeError: dictionnaire a changé la taille pendant l'itération' avec Python 3.5 –

+0

' '' def del_none (d): "" " Supprimer les clés avec la valeur' 'None'' et la chaîne vide dans un dictionnaire, récursive. Cela ne modifie pas l'entrée, mais copie le dictionnaire. dictionnaires d'enfants sont également copiés. Aucun autre objets sont copiés. « » » = D.Copy rez() pour la clé, valeur d .items(): si la valeur est None ou value == '': del rez [clé] elif isinstance (valeur, dict): rez [clé] = del_none (valeur) return re z''' –

+1

@AleksandrPanzin: J'ai mis à jour le code pour cibler Python 3 avec des notes pour Python 2. Ce * a été écrit il y a sept ans! Je l'ai laissé comme une modification sur place, cependant. –

0
def excludeNone(d): 
    for k in list(d): 
     if k in d: 
      if type(d[k]) == dict: 
       excludeNone(d[k]) 
      if not d[k]: 
       del d[k] 
+4

Il serait plus sûr d'utiliser 'si d [k] n'est pas None' au lieu de' sinon d [k] '- sinon les chaînes vides et les valeurs 0 seront également exclues de la sortie. –

6
>>> def cleandict(d): 
...  if not isinstance(d, dict): 
...   return d 
...  return dict((k,cleandict(v)) for k,v in d.iteritems() if v is not None) 
... 
>>> mydict = dict(dict1=dict(key1='value1', key2=None)) 
>>> print cleandict(mydict) 
{'dict1': {'key1': 'value1'}} 
>>> 

Je n'aime pas utiliser del en général, en changeant le dictionnaire existant peut avoir des effets subtils en fonction de la façon dont ils sont créés. La création de nouveaux dictionnaires avec None supprimé empêche tous les effets secondaires.