2013-02-15 95 views
11
>>> 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

回答

22

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

1

另外,如果你想趕上(每級),你可以使用一個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

相關問題