json。load允许在字典中复制键,覆盖第一个值

时间:2022-02-02 07:04:30
>>> 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'}}}

As you can see members with key '1' is overwritten when I use json.dumps()

如您所见,当我使用json.dumps()时,会覆盖键为“1”的成员

Is there any way to catch it as exception in python, saying found duplicate keys in request from client ?

在python中有什么方法将它捕获为异常,说在客户端请求中找到重复的键吗?

3 个解决方案

#1


24  

The rfc 4627 for application/json media type recommends unique keys but it doesn't forbid them explicitly:

应用/json媒体类型的rfc 4627推荐使用唯一键,但没有明确禁止:

The names within an object SHOULD be unique.

对象中的名称应该是惟一的。

From rfc 2119:

rfc 2119:

SHOULD This word, or the adjective "RECOMMENDED", mean that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.

如果这个词,或形容词“推荐”,意味着在特定的情况下可能存在忽视某一项的正当理由,但在选择不同的课程之前,必须理解并仔细权衡其全部含义。

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'

#2


1  

Alternatively if you want to catch all the duplicate keys (per level) you can use a collections.Counter

或者,如果您想捕获所有重复的键(每一层),您可以使用collections.Counter

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)

#3


0  

This is a linter-fixed version of the answer by jfs. Issues highlighted by various linters were addressed. It is also modernized for Python 3.6+ to use f-strings.

这是jfs回答的一个linter-fixed版本。讨论了不同的linters所强调的问题。Python 3.6+使用f-strings也实现了现代化。

import json

def check_for_duplicate_keys(ordered_pairs):
    """Raise ValueError if a duplicate key exists in provided ordered list of pairs, otherwise return a dict."""
    dict_out = {}
    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))

#1


24  

The rfc 4627 for application/json media type recommends unique keys but it doesn't forbid them explicitly:

应用/json媒体类型的rfc 4627推荐使用唯一键,但没有明确禁止:

The names within an object SHOULD be unique.

对象中的名称应该是惟一的。

From rfc 2119:

rfc 2119:

SHOULD This word, or the adjective "RECOMMENDED", mean that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.

如果这个词,或形容词“推荐”,意味着在特定的情况下可能存在忽视某一项的正当理由,但在选择不同的课程之前,必须理解并仔细权衡其全部含义。

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'

#2


1  

Alternatively if you want to catch all the duplicate keys (per level) you can use a collections.Counter

或者,如果您想捕获所有重复的键(每一层),您可以使用collections.Counter

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)

#3


0  

This is a linter-fixed version of the answer by jfs. Issues highlighted by various linters were addressed. It is also modernized for Python 3.6+ to use f-strings.

这是jfs回答的一个linter-fixed版本。讨论了不同的linters所强调的问题。Python 3.6+使用f-strings也实现了现代化。

import json

def check_for_duplicate_keys(ordered_pairs):
    """Raise ValueError if a duplicate key exists in provided ordered list of pairs, otherwise return a dict."""
    dict_out = {}
    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))