为了账号安全,请及时绑定邮箱和手机立即绑定

Python json解析器允许重复键

Python json解析器允许重复键

qq_遁去的一_1 2020-02-02 14:20:47
我需要解析一个json文件,不幸的是,该文件不遵循原型。我的数据有两个问题,但是我已经找到了解决方法,所以我只在最后提一下,也许有人也可以提供帮助。所以我需要解析这样的条目:    "Test":{        "entry":{            "Type":"Something"                },        "entry":{            "Type":"Something_Else"                }           }, ...json默认解析器更新字典,因此仅使用最后一个条目。我不得不以某种方式存储另一个,我也不知道如何做到这一点。我还必须按照它们在文件中出现的顺序将键存储在几个字典中,这就是为什么我使用OrderedDict这样做的原因。它工作正常,所以如果有任何办法可以用重复的条目来扩展它,我将不胜感激。我的第二个问题是,这个非常相同的json文件包含这样的条目:         "Test":{                   {                       "Type":"Something"                   }                }当Json.load()函数到达json文件中的该行时,将引发异常。解决此问题的唯一方法是自己手动卸下内支架。提前致谢
查看完整描述

2 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

您可以用JSONDecoder.object_pairs_hook来自定义JSONDecoder解码对象的方式。这个钩子函数将被传递一个(key, value)您通常会对其进行一些处理的成对列表,然后变成一个dict。


但是,由于Python字典不允许重复的键(而且您根本无法更改键),因此在(key, value)解码JSON时,您可以在挂钩中保持不变地返回对,并获得嵌套的对列表:


from json import JSONDecoder


def parse_object_pairs(pairs):

    return pairs



data = """

{"foo": {"baz": 42}, "foo": 7}

"""


decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)

obj = decoder.decode(data)

print obj

输出:


[(u'foo', [(u'baz', 42)]), (u'foo', 7)]

您如何使用此数据结构取决于您。如上所述,Python字典不允许重复的键,而且没有办法解决。您甚至将如何基于密钥进行查找?dct[key]会模棱两可。


因此,您既可以实现自己的逻辑来以期望的方式处理查找,也可以实现某种避免碰撞的功能,以使键(如果不是)变得唯一,然后从嵌套列表中创建字典。


编辑:既然您说过要修改重复键以使其唯一,请按以下步骤进行操作:


from collections import OrderedDict

from json import JSONDecoder



def make_unique(key, dct):

    counter = 0

    unique_key = key


    while unique_key in dct:

        counter += 1

        unique_key = '{}_{}'.format(key, counter)

    return unique_key



def parse_object_pairs(pairs):

    dct = OrderedDict()

    for key, value in pairs:

        if key in dct:

            key = make_unique(key, dct)

        dct[key] = value


    return dct



data = """

{"foo": {"baz": 42, "baz": 77}, "foo": 7, "foo": 23}

"""


decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)

obj = decoder.decode(data)

print obj

输出:


OrderedDict([(u'foo', OrderedDict([(u'baz', 42), ('baz_1', 77)])), ('foo_1', 7), ('foo_2', 23)])

该make_unique函数负责返回无冲突键。在这个例子中,它只是后缀与关键_n地方n是一个递增计数器-只是它适应您的需求。


由于object_pairs_hook完全按照JSON文档中出现的顺序接收对,因此也可以使用来保留该顺序OrderedDict,我也将其包括在内。


查看完整回答
反对 回复 2020-02-02
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

非常感谢@Lukas Graf,我通过实现自己的钩子函数版本也使它正常工作


def dict_raise_on_duplicates(ordered_pairs):

  count=0

  d=collections.OrderedDict()

  for k,v in ordered_pairs:

      if k in d:

          d[k+'_dupl_'+str(count)]=v

          count+=1

      else:

          d[k]=v

  return d

剩下的唯一事情就是自动摆脱双括号,我完成了:D再次感谢


查看完整回答
反对 回复 2020-02-02
  • 2 回答
  • 0 关注
  • 563 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信