您总是可以手动构造这样的字符串值.
另一方面,可以使CPython json模块对重复的密钥进行编码.这在Python 2中非常棘手,因为json模块根本不尊重鸭子类型.
直接的解决方案是从collections.Mapping继承-嗯,这是不可能的,因为“ MyMapping不是可序列化的JSON”.
下一类尝试将dict子类化-很好,但是如果json.dumps注意到类型是dict,它会跳过调用__len__并直接看到基础的dict-如果它为空,则直接输出{},因此很清楚我们是否伪造方法,基础字典不能为空.
下一个喜悦的来源是实际上调用了__iter__,它会迭代密钥.对于每个键,都会调用__getitem__,因此我们需要记住给定键返回的对应值是什么…因此,我们得出了一个非常丑陋的Python 2解决方案:
import json
class FakeDict(dict):
def __init__(self, items):
# need to have something in the dictionary
self['something'] = 'something'
self.items = items
def __getitem__(self, key):
return self.last_val
def __iter__(self):
subiter = iter(self.items)
def generator():
for key, value in self.items:
self.last_val = value
yield key
return generator()
print json.dumps(FakeDict([('a', 5), ('a', 6)]), sort_keys=False)
在CPython 3.3中,它稍微容易些…不,collections.abc.Mapping不起作用,是的,您需要将一个dict子类化,是的,您需要伪造字典中包含内容…但是内部JSON编码器调用项目而不是__iter__和__getitem__!
因此在Python 3上:
import json
class FakeDict(dict):
def __init__(self, items):
self['something'] = 'something'
self._items = items
def items(self):
return self._items
print(json.dumps(FakeDict([('a', 1), ('a', 2)])))
打印出来
{"a": 1, "a": 2}