Python json.loads多个回调参数

时间:2019-04-01 17:26:12

标签: python

我有一些从数据库解析的json,我需要做两件事。

  1. 确保使用(OrderedDict)维护订单,该功能是内置函数并且不能修改
  2. 检查并重命名重复键,这是一个自定义函数(rename_duplicate)
def rename_duplicate(pairs):
        d = {}
        k_counter = Counter(defaultdict(int))
        for k, v in pairs:
            d[k+str(k_counter[k])] = v
            k_counter[k] += 1
  return d

在使用json.loads时如何同时使用两者?

json.loads(raw_text_data, object_pairs_hook=OrderedDict,rename_duplicate)

错误

d = json.loads(row['Commands'], object_pairs_hook=OrderedDict,rename_duplicate)
SyntaxError: non-keyword arg after keyword arg

2 个答案:

答案 0 :(得分:1)

我同意amrx的观点,object_pairs_hook=OrderedDict,rename_duplicate不是获得所需内容的正确语法。似乎您正在尝试告诉函数object_pairs_hook应该返回OrderedDict,并且应该调用rename_duplicate。但是,您不能像这样*为一个参数赋予两个值。只要您是从rename_duplicates返回的内容,我就不需要在此处指定OrderedDict。

import json
from collections import OrderedDict, Counter

def rename_duplicates(pairs):
    d = OrderedDict()
    c = Counter()
    for k,v in pairs:
        new_k = k + str(c[k])
        d[new_k] = v
        c[k] += 1
    return d

s = '{"foo": "bar", "foo": "qux", "troz": "zort", "foo": "coconuts"}'
print(json.loads(s, object_pairs_hook=rename_duplicates))

结果:

OrderedDict([('foo0', 'bar'), ('foo1', 'qux'), ('troz0', 'zort'), ('foo2', 'coconuts')])

(*好吧,从技术上讲,您可以向它传递一个包含两个值的元组,但是由于该特定参数期望可调用,而元组不可调用,它仍然会崩溃)


编辑:从您的问题描述中我不清楚,是否还应该重命名唯一键,以及是否在第一次遇到非重键时应该重命名。如果这两个答案都为“否”,那么只需对代码稍作更改即可实现。

import json
from collections import OrderedDict, Counter

def rename_duplicates(pairs):
    d = OrderedDict()
    c = Counter()
    for k,v in pairs:
        if k not in c:
            new_k = k
        else:
            new_k = k + str(c[k])
        d[new_k] = v
        c[k] += 1
    return d

s = '{"foo": "bar", "foo": "qux", "troz": "zort", "foo": "coconuts"}'
print(json.loads(s, object_pairs_hook=rename_duplicates))

结果:

OrderedDict([('foo', 'bar'), ('foo1', 'qux'), ('troz', 'zort'), ('foo2', 'coconuts')])

答案 1 :(得分:0)

除了您的特定要求外,还有一个潜在的错误。当我们将参数传递给Python中的函数或方法时,我们不能在关键字参数之后传递non keyword argument

def foo(x, y=None, z=None):
   pass

// we can call foo
foo(10, 11, 12)
foo(10, 11, z=12)
foo(x=10, z=7, y=9)

// But we cannot call foo like this
foo(x=90, 12, 3)
// Once we start using a keyword argument, all arguments after that must be a keyword argument, otherwise we will have compile time error.

对于消除重复项,我建议处理json.loads的结果以消除重复项。