从 JSON 序列化中排除空/null 值

发布于 2024-10-04 03:01:38 字数 373 浏览 7 评论 0原文

我正在使用 Python 和 simplejson 将多个嵌套字典序列化为 JSON。

有没有办法自动排除空/空值?

例如,将其序列化为:

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

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

Jackson 与 Java 结合使用时,您可以使用 Inclusion.NON_NULL 来执行此操作。有等效的 simplejson 吗?

I am serializing multiple nested dictionaries to JSON using Python with simplejson.

Is there any way to automatically exclude empty/null values?

For example, serialize this:

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

to

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

When using Jackson with Java you can use Inclusion.NON_NULL to do this. Is there a simplejson equivalent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

夜还是长夜 2024-10-11 03:01:38
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

示例用法:

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

然后您可以将其提供给 json

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

Sample usage:

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

Then you can feed that to json.

夏九 2024-10-11 03:01:38

我的 Python3 版本的优点是不更改输入,以及递归到嵌套在列表中的字典:

def clean_nones(value):
    """
    Recursively remove all None values from dictionaries and lists, and returns
    the result as a new dictionary or list.
    """
    if isinstance(value, list):
        return [clean_nones(x) for x in value if x is not None]
    elif isinstance(value, dict):
        return {
            key: clean_nones(val)
            for key, val in value.items()
            if val is not None
        }
    else:
        return value

例如:

a = {
    "a": None,
    "b": "notNone",
    "c": ["hello", None, "goodbye"],
    "d": [
        {
            "a": "notNone",
            "b": None,
            "c": ["hello", None, "goodbye"],
        },
        {
            "a": "notNone",
            "b": None,
            "c": ["hello", None, "goodbye"],
        }
    ]
}


print(clean_nones(a))

结果如下:

{
    'b': 'notNone',
    'c': ['hello', 'goodbye'],
    'd': [
        {
            'a': 'notNone',
            'c': ['hello', 'goodbye']
        },
        {
            'a': 'notNone',
            'c': ['hello', 'goodbye']
        }
    ]
}

My Python3 version of this has the benefit of not changing the input, as well as recursion into dictionaries nested in lists:

def clean_nones(value):
    """
    Recursively remove all None values from dictionaries and lists, and returns
    the result as a new dictionary or list.
    """
    if isinstance(value, list):
        return [clean_nones(x) for x in value if x is not None]
    elif isinstance(value, dict):
        return {
            key: clean_nones(val)
            for key, val in value.items()
            if val is not None
        }
    else:
        return value

For example:

a = {
    "a": None,
    "b": "notNone",
    "c": ["hello", None, "goodbye"],
    "d": [
        {
            "a": "notNone",
            "b": None,
            "c": ["hello", None, "goodbye"],
        },
        {
            "a": "notNone",
            "b": None,
            "c": ["hello", None, "goodbye"],
        }
    ]
}


print(clean_nones(a))

results in this:

{
    'b': 'notNone',
    'c': ['hello', 'goodbye'],
    'd': [
        {
            'a': 'notNone',
            'c': ['hello', 'goodbye']
        },
        {
            'a': 'notNone',
            'c': ['hello', 'goodbye']
        }
    ]
}
享受孤独 2024-10-11 03:01:38
>>> 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'}}
>>> 

一般来说,我不喜欢使用 del,更改现有字典可能会产生微妙的影响,具体取决于它们的创建方式。创建删除 None 的新词典可以防止所有副作用。

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

I don't like using del in general, changing the existing dictionary can have subtle effects depending on how they are created. Creating new dictionaries with None removed prevents all side effect.

深海蓝天 2024-10-11 03:01:38

你可以尝试这个方法。就我而言(我使用 python 3),它运行良好。

def to_json(self):
    return json.dumps(self,
                      default=lambda o: dict((key, value) for key, value in o.__dict__.items() if value),
                      indent=4,
                      allow_nan=False)

You can try this approach. In my case (I use python 3), it works well.

def to_json(self):
    return json.dumps(self,
                      default=lambda o: dict((key, value) for key, value in o.__dict__.items() if value),
                      indent=4,
                      allow_nan=False)
意中人 2024-10-11 03:01:38

此解决方案是对 @eric 的上面的更正,它处理列表 正确输入。

规范 JSON 字典中的 可以是以下 3 种类型之一:

  • 字典
  • 列表
  • 值类型(字符串、<代码>整数或浮点

注意:假设我们在这里处理的是规范 JSON 字典,它实际上只能包含上述类型。如果字典包含上述类型之外的其他类型(例如元组、自定义类...),则此解决方案将无法按预期工作。

此解决方案(如下)与 @eric 的原始解决方案之间的本质区别在于 list 可以包含 dictionary 类型的元素,我们希望从其中删除元素 <代码>无值。

def cleandict(d):
    if isinstance(d, dict):
        return {k: cleandict(v) for k, v in d.items() if v is not None}
    elif isinstance(d, list):
        return [cleandict(v) for v in d]
    else:
        return d

注意:请记住,我们不能从列表中删除None元素,因为这会影响列表数据的结构完整性。如果某些(或全部)列表元素具有 None 值,则它们应按原样保留在列表结构中,以保留列表的原始结构含义/完整性。

This solution is correction of the one above from @eric which does not handle list type corectly.

Values in canonical JSON dictionary can be of one of following 3 types:

  • dictionary
  • list
  • value type (string, integer or floating point)

Note: Assumption is that we are dealing here with canonical JSON dictionary which can really contain only above mentioned types. If dictionary contains other types then ones mentioned above (e.g. tuples, custom classes, ...), then this solution won't work as expected.

The essential difference between this solution (below) and the original one from @eric is that list can contain elements of dictionary type from iside of which we want to drop elements with None value.

def cleandict(d):
    if isinstance(d, dict):
        return {k: cleandict(v) for k, v in d.items() if v is not None}
    elif isinstance(d, list):
        return [cleandict(v) for v in d]
    else:
        return d

Note: Please keep in mind that we must NOT remove None elements from the list since it would affect structural integrity of the list data. If some ( or all) of list elements have None value, they shall remain listed in the list structure as they were in order to preserve original structural meaning/integrity of the list.

深海里的那抹蓝 2024-10-11 03:01:38
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]
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]
不再让梦枯萎 2024-10-11 03:01:38

它对我有用:

当字典有 dict/list/tuple 值时......

例如,它是我的对象:

dict_obj = {
    'inline_keyboard': [
        [
            {'text': '0-0', 'url': None, 'login_url': None, 'callback_data': '0-0', 'switch_inline_query': None},
            {'text': '0-1', 'url': None, 'login_url': None, 'callback_data': '0-1', 'switch_inline_query': None}
        ],
        [
            {'text': '1-0', 'url': None, 'login_url': None, 'callback_data': '1-0', 'switch_inline_query': None},
            {'text': '1-1', 'url': None, 'login_url': None, 'callback_data': '1-1', 'switch_inline_query': None}
        ],
        [
            {'text': '2-0', 'url': None, 'login_url': None, 'callback_data': '2-0', 'switch_inline_query': None}
        ]
    ]
}

我写了这个函数:

def delete_none_values(obj):
    if isinstance(obj, dict):
        for k, v in list(obj.items()):
            if v is None:
                del obj[k]
            elif isinstance(v, dict):
                delete_none_values(v)
            elif isinstance(v, (list, tuple)):
                for _ in v:
                    delete_none_values(_)
    elif isinstance(obj, (list, tuple)):
        for _ in obj:
            delete_none_values(_)
    return obj

然后当使用这个函数时:

from json import dumps

print(
    dumps(
        delete_none_values(dict_obj.copy()),
        indent=2
    )
)

输出是:

{
  "inline_keyboard": [
    [
      {"text": "0-0", "callback_data": "0-0"},
      {"text": "0-1", "callback_data": "0-1"}
    ],
    [
      {"text": "1-0", "callback_data": "1-0"},
      {"text": "1-1", "callback_data": "1-1"}
    ],
    [
      {"text": "2-0", "callback_data": "2-0"}
    ]
  ]
}

It works for me:

When dictionary has dict/list/tuple values ....

for example it is my object:

dict_obj = {
    'inline_keyboard': [
        [
            {'text': '0-0', 'url': None, 'login_url': None, 'callback_data': '0-0', 'switch_inline_query': None},
            {'text': '0-1', 'url': None, 'login_url': None, 'callback_data': '0-1', 'switch_inline_query': None}
        ],
        [
            {'text': '1-0', 'url': None, 'login_url': None, 'callback_data': '1-0', 'switch_inline_query': None},
            {'text': '1-1', 'url': None, 'login_url': None, 'callback_data': '1-1', 'switch_inline_query': None}
        ],
        [
            {'text': '2-0', 'url': None, 'login_url': None, 'callback_data': '2-0', 'switch_inline_query': None}
        ]
    ]
}

I wrote this function:

def delete_none_values(obj):
    if isinstance(obj, dict):
        for k, v in list(obj.items()):
            if v is None:
                del obj[k]
            elif isinstance(v, dict):
                delete_none_values(v)
            elif isinstance(v, (list, tuple)):
                for _ in v:
                    delete_none_values(_)
    elif isinstance(obj, (list, tuple)):
        for _ in obj:
            delete_none_values(_)
    return obj

And then when use this fuction:

from json import dumps

print(
    dumps(
        delete_none_values(dict_obj.copy()),
        indent=2
    )
)

output is:

{
  "inline_keyboard": [
    [
      {"text": "0-0", "callback_data": "0-0"},
      {"text": "0-1", "callback_data": "0-1"}
    ],
    [
      {"text": "1-0", "callback_data": "1-0"},
      {"text": "1-1", "callback_data": "1-1"}
    ],
    [
      {"text": "2-0", "callback_data": "2-0"}
    ]
  ]
}
怪我闹别瞎闹 2024-10-11 03:01:38

如果“url”在一个地方有价值,您是否可以保留它,如果在另一个地方没有价值,则可以删除它?

'inline_keyboard': [
        [
            {'text': '0-0', 'url': 'someValue', 'login_url': None, 'callback_data': '0-0', 'switch_inline_query': None},
            {'text': '0-1', 'url': None, 'login_url': None, 'callback_data': '0-1', 'switch_inline_query': None}
        ],
        [
            {'text': '1-0', 'url': None, 'login_url': None, 'callback_data': '1-0', 'switch_inline_query': None},
            {'text': '1-1', 'url': None, 'login_url': None, 'callback_data': '1-1', 'switch_inline_query': None}
        ],
        [
            {'text': '2-0', 'url': None, 'login_url': None, 'callback_data': '2-0', 'switch_inline_query': None}
        ]
]

Could you maybe remain 'url' if it has value in one place and remove it if it none on another place?

'inline_keyboard': [
        [
            {'text': '0-0', 'url': 'someValue', 'login_url': None, 'callback_data': '0-0', 'switch_inline_query': None},
            {'text': '0-1', 'url': None, 'login_url': None, 'callback_data': '0-1', 'switch_inline_query': None}
        ],
        [
            {'text': '1-0', 'url': None, 'login_url': None, 'callback_data': '1-0', 'switch_inline_query': None},
            {'text': '1-1', 'url': None, 'login_url': None, 'callback_data': '1-1', 'switch_inline_query': None}
        ],
        [
            {'text': '2-0', 'url': None, 'login_url': None, 'callback_data': '2-0', 'switch_inline_query': None}
        ]
]
冰之心 2024-10-11 03:01:38

我使用了 MatanRubin 函数并对其进行了扩展,以便它还可以过滤 Nan(浮点)和 Null(字符串),以便能够与 Php API 进行通信。

from math import isnan

def clean_nones(value):
    """
    Recursively remove all None values from dictionaries and lists, and returns
    the result as a new dictionary or list.
    """
    def checkNan(value):
        if isinstance(value, float) and isnan(value):
            return True if (isinstance(value, float) and isnan(value)) else False
        
    if isinstance(value, list):
        return [clean_nones(x) for x in value if (x is not None and  x != 'NULL' and not checkNan(x))]
    elif isinstance(value, dict):
        return {
            key: clean_nones(val)
            for key, val in value.items()
            if (val is not None and val != 'NULL' and not checkNan(val))
        }
    else:
        return value

cleanedJson = clean_nones(toCleanJson)

I used the MatanRubin function and extended it so that it also filters Nan (float) and Null (string) to be able to talk with a Php API.

from math import isnan

def clean_nones(value):
    """
    Recursively remove all None values from dictionaries and lists, and returns
    the result as a new dictionary or list.
    """
    def checkNan(value):
        if isinstance(value, float) and isnan(value):
            return True if (isinstance(value, float) and isnan(value)) else False
        
    if isinstance(value, list):
        return [clean_nones(x) for x in value if (x is not None and  x != 'NULL' and not checkNan(x))]
    elif isinstance(value, dict):
        return {
            key: clean_nones(val)
            for key, val in value.items()
            if (val is not None and val != 'NULL' and not checkNan(val))
        }
    else:
        return value

cleanedJson = clean_nones(toCleanJson)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文