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

问题描述:

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

正如你可以看到成员键“1”被覆盖,当我使用json.dumps()json.loads允许重复键在字典中,覆盖第一个值

有没有办法抓住它作为例外蟒蛇,说在客户端的请求中发现重复的键?

+1

相关的所有重复键:[SimpleJson相同命名实体的处理](HTTP://计算器.com/questions/7825261/simplejson-handling-of-same-named-entities) – jfs 2013-02-15 20:00:47

The rfc 4627 for application/json media type建议独特的密钥,但它并没有明确禁止他们:

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

rfc 2119

应该这个词,或“推荐”的形容词,意味着有
可能存在在特定情况下正当的理由忽略
特定项目,但在选择不同的课程之前,必须仔细权衡全部含义并且仔细权衡。

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' 
+0

+1好吧,它看起来好多了:) – root 2013-02-15 20:12:53

+0

是的,那是我在找的..Thx ..不过,json.load ()图书馆应该提供一些可以做类似的事情。 – 2013-02-15 22:11:37

+2

@AuujAcharya:问题是,有好的一个普通的词典,一个“multidict”,一个“多语言双关语词典”,一个“提高双语词典”(包含ValueError或KeyError?)和其他可能的用例。并且你需要'json.loads'和'json.load','csv.DictReader'和'yaml.load'等完全相同的东西。 (请参阅关于'csv'的python-ideas的当前讨论。)您不想为所有可能的加载函数编写所有可能的行为。 'object_pairs_hook'似乎是解耦的正确方法。 – abarnert 2013-02-15 23:07:21

另外,如果你想赶上(每级),你可以使用一个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) 
+1

你的计数器正在计算出现次数,因此要查找出现多次的密钥(即重复),列表理解中的条件应该是'如果我> 1'而不是'如果我> 0'。 – 2015-11-22 21:02:23

+0

其实,即使在这个修正之后,它仍然不像广告那样工作。尽管如此,J.F.塞巴斯蒂安的代码仍然有效。我建议使用它,即使这种方法似乎有些优雅,因为它使用列表解析而不是循环。 – 2015-11-22 21:12:59

+0

快速修复将是'self.update(args [0])',即没有星号。 KeyWatcher只用一个参数来调用,因此'* args'根本就没有帮助。 – VPfB 2017-01-19 08:17:00