从嵌套字典中删除所有空值。

3

我将使用下面的嵌套字典作为json示例:

{
  "DICT": {
    "List of dict": [
      { #first dict inside the outer list
        "K1": "V1",
        "K2": "V2",
        "K3": "V3",
        "K4": [
          {
            "K4_1_1": "V4_1"
          },
          {
            "K4_2_1": "V4_2"
          },
          {
            "K4_3_1": null
          }
        ],
        "K5 is a list of Dict": [
          {
            "K5_1_1": "V5_1",
            "K5_1_2": "V5_2",
            "K5_1_3": "V5_3",
            "K5_1_4": "V5_4"
          },
          {
            "K5_2_1": "V5_1",
            "K5_2_2": "V5_2",
            "K5_2_3": "V5_3",
            "K5_2_4": "V5_4"
          }
        ]
      },
      { #second dict in the outerlist
        "K1": "V1",
        "K2": "V2",
        "K3": "V3",
        "K4": [
          {
            "K4_1_1": "V4_1_1"
          },
          {
            "K4_2_1": "V4_2_1"
          }
        ],
        "K5": {
          "K5_1_1": "V_1_1",
          "K5_1_2": "V_1_2",
          "K5_1_3": null,
          "K5_1_4": null
        }
      }
    ]
  }
}

请注意,K4K5始终是dict列表。我需要摆脱所有的空值,无论它们在字典内部还是在列表内部有多深。因此,我编写了以下Python函数,但输出结果仍然相同,所有的 None 值仍然存在:
def RemoveNones(Dict):
    for k, v in Dict.items():
        if type(v) == collections.OrderedDict:
            RemoveNones(v)
        elif type(v) == list:
            for i in v:
                RemoveNones(i)
        else:
            Dict = dict((K,V) for K,V in Dict.items() if V!=None)

我的字典不是dict,而是<class 'collections.OrderedDict'>

1个回答

2
type() 的语法如下:if type(v) is list:(不是 ==)。因此,您需要像这样的东西:
import json
from collections import OrderedDict

raw_text = '{"DICT":{"List of dict":[{"K1":"V1","K2":"V2","K3":"V3","K4":[{"K4_1_1":"V4_1"},{"K4_2_1":"V4_2"},{"K4_3_1":null}],"K5 is a list of Dict":[{"K5_1_1":"V5_1","K5_1_2":"V5_2","K5_1_3":"V5_3","K5_1_4":"V5_4"},{"K5_2_1":"V5_1","K5_2_2":"V5_2","K5_2_3":"V5_3","K5_2_4":"V5_4"}]},{"K1":"V1","K2":"V2","K3":"V3","K4":[{"K4_1_1":"V4_1_1"},{"K4_2_1":"V4_2_1"}],"K5":{"K5_1_1":"V_1_1","K5_1_2":"V_1_2","K5_1_3":null,"K5_1_4":null}}]}}'

raw_json = json.JSONDecoder(object_pairs_hook=OrderedDict).decode(raw_text)

def remove_nulls(x):
    if type(x) is list:
        return [remove_nulls(v) for v in x if v is not None]
    elif type(x) is OrderedDict:
        return OrderedDict((k,remove_nulls(v)) for k,v in x.items() if v is not None)
    else:
        return x

de_nullified_json = remove_nulls(raw_json)
print(json.dumps(de_nullified_json, indent=2))

输出:

{
  "DICT": {
    "List of dict": [
      {
        "K1": "V1",
        "K2": "V2",
        "K3": "V3",
        "K4": [
          {
            "K4_1_1": "V4_1"
          },
          {
            "K4_2_1": "V4_2"
          },
          {}
        ],
        "K5 is a list of Dict": [
          {
            "K5_1_1": "V5_1",
            "K5_1_2": "V5_2",
            "K5_1_3": "V5_3",
            "K5_1_4": "V5_4"
          },
          {
            "K5_2_1": "V5_1",
            "K5_2_2": "V5_2",
            "K5_2_3": "V5_3",
            "K5_2_4": "V5_4"
          }
        ]
      },
      {
        "K1": "V1",
        "K2": "V2",
        "K3": "V3",
        "K4": [
          {
            "K4_1_1": "V4_1_1"
          },
          {
            "K4_2_1": "V4_2_1"
          }
        ],
        "K5": {
          "K5_1_1": "V_1_1",
          "K5_1_2": "V_1_2"
        }
      }
    ]
  }
}

谢谢您的解释和答案,这很有效。我一直在观察您的编辑,为什么我们从 json.load(f) 转到了 json.JSONDecoder(object_pairs_hook=OrderedDict).decode(raw_text)?是为了使输出与输入顺序相同吗?至于我的 ==!=,我来自 C++ 背景。 - Hadi Farah
json.load(f) 生成常规的 dict 对象(而不是 OrderedDicts),因此您会失去元素的顺序。 - Richard Inglis
但是输出是否正确?一些元素是空的 { } - Richard Inglis
是的,我可以处理空的 {},因为后来我会使用 gettext() 处理空括号,但不处理 None 值。 - Hadi Farah
1
这里有一个很好的关于is==的解释:https://dev59.com/X2Yq5IYBdhLWcg3wui_F - Richard Inglis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接