json.loads允许字典中有重复的键,覆盖第一个值

问题描述 投票:20回答:4
>>> raw_post_data = request.raw_post_data
>>> print raw_post_data
{"group":{"groupId":"2", "groupName":"GroupName"}, "members":{"1":{"firstName":"fName","lastName":"LName","address":"address"},"1": {"firstName":"f_Name","lastName":"L_Name","address":"_address"}}}
>>> create_request = json.loads(raw_post_data)
>>> print create_request
{u'group': {u'groupName': u'GroupName', u'groupId': u'2'}, u'members': {u'1': {u'lastName': u'L_Name', u'firstName': u'f_Name', u'address': u'_address'}}}

如您所见,当我使用json.dumps()时,具有键'1'的成员将被覆盖

有什么方法可以将其作为python中的异常捕获,说在客户端的请求中发现重复的键?

python json
4个回答
34
投票

The rfc 4627 for application/json media type建议使用唯一键,但不会明确禁止它们:

对象内的名称应唯一。

来自application/json

SHOULD这个词,或形容词“ RECOMMENDED”,表示在那里在特定情况下可能存在正当理由而忽略特定项目,但必须理解全部含义并在选择其他路线之前,请仔细权衡一下。

rfc 2119

2
投票

这是import json def dict_raise_on_duplicates(ordered_pairs): """Reject duplicate keys.""" d = {} for k, v in ordered_pairs: if k in d: raise ValueError("duplicate key: %r" % (k,)) else: d[k] = v return d json.loads(raw_post_data, object_pairs_hook=dict_raise_on_duplicates) # -> ValueError: duplicate key: u'1' 的固定棉绒并带有类型注释的版本。解决了各种短毛猫强调的问题。对于Python 3.6+,它也经过了现代化的改进,可以使用f字符串。

answer by jfs

1
投票

或者,如果您想捕获所有重复的按键(每级),可以使用import json from typing import Any, Dict, Hashable, List, Tuple def check_for_duplicate_keys(ordered_pairs: List[Tuple[Hashable, Any]]) -> Dict: """Raise ValueError if a duplicate key exists in provided ordered list of pairs, otherwise return a dict.""" dict_out: Dict = {} for key, val in ordered_pairs: if key in dict_out: raise ValueError(f'Duplicate key: {key}') else: dict_out[key] = val return dict_out json.loads('{"x": 1, "x": 2}', object_pairs_hook=check_for_duplicate_keys)

collections.Counter

0
投票

我根据此问题的其他用户发布的解决方案写的一个替代方案是将这些重复项转换为数组:

from collections import Counter

class KeyWatcher(dict):

    def __init__(self, *args):
        duplicates = [d for d,i in Counter([pair[0] for pair in args[0]]).items() if i > 0]
        if duplicates:
            raise KeyError("Can't add duplicate keys {} to a json message".format(duplicates))
        self.update(*args[0])

json.loads(raw_post_data, object_pairs_hook=KeyWatcher)

然后:

def array_on_duplicate_keys(ordered_pairs):
    """Convert duplicate keys to arrays."""
    d = {}
    for k, v in ordered_pairs:
        if k in d:
            if type(d[k]) is list:
                d[k].append(v)
            else:
                d[k] = [d[k],v]
        else:
           d[k] = v
    return d

为您提供输出:

dict = json.loads('{"x": 1, "x": 2}', object_pairs_hook=array_on_duplicate_keys)

稍后,可以通过使用以下命令轻松检查条目重复的含义:

{'x': [1, 2]}
© www.soinside.com 2019 - 2024. All rights reserved.