【问题标题】:How to override JSONDecoder to handle certain string matches differently如何覆盖 JSONDecoder 以不同方式处理某些字符串匹配
【发布时间】:2019-02-21 01:07:33
【问题描述】:

我想更改 json 文件中的某些值(嵌套字典和数组)。我认为一个方便的方法是利用 JSONDecoder。

但是,它并没有像我预期的那样工作。我已经采用了完全相同的方法让 JSONEncoder 将 np.arrays 转换为列表,这样它就不会破坏编码器。

在没有让它做我想做的事之后,我想也许可以试试解码器。同样的问题,它似乎从不调用默认值来处理字符串。也许default 在处理字符串时不会被调用,只是在处理其他类型的对象时?

# key, val are arguments passed in, e.g. ("bar", "2.0rc1")
# Replace the value "2.0rc1" everywhere the "bar" key is found

class StringReplaceDecoder(json.JSONDecoder):
    def default(self, obj):
        if isinstance(obj, str):
            print("Handling obj str: {}".format(obj))
            if obj == key:
                return val
        return json.JSONEncoder.default(self, obj)


json_dump = json.dumps(dict)
json_load = json.loads(json_dump, cls=StringReplaceDecoder)

# Example input
{a:{foo:"", bar:"1.3"}, b:{d:{foo:""}, z:{bar:"1.5"}}}
# Example desired output:
{a:{foo:"", bar:"2.0rc1"}, b:{d:{foo:""}, z:{bar:"2.0rc1"}}}

【问题讨论】:

  • 经过一些测试并查看源代码后,我几乎可以肯定行为是从不为字符串类型输入默认值。因此,适用于 np.ndarray 类型的方法在这里不起作用。那么有没有另一种方法来获得特定字符串的自定义行为?
  • 您可以创建自己的“类似字符串”类型(不是从str 派生的),并在遇到其中一个实例时覆盖默认编码器所做的事情。另见How to set the number of float digits JSONEncoder produces?
  • 首先,您的示例子类 JSONDecoder,它没有 default 方法(因为它只解析 json 编码的字符串)。其次,JSONEncoderdefault 方法仅对 自动支持的对象调用(因此不适用于 strint、@987654332 @, ETC)。这一切都在json docs 中解释得很清楚。因此,我建议您忘记json,只需编写一个简单的递归函数来理解您的特定数据结构。
  • 啊,谢谢。只有编码器有默认值才有意义。

标签: python json dictionary


【解决方案1】:

在找到一个行之有效的解决方案后,我发现了一个在以前的谷歌搜索中没有出现过的更优秀的一个班轮。

我的问题的正确答案是from nested_lookup import nested_update

对于它的价值,我还发现 object_hook 也完全符合我的要求:

def val_hook(obj):
    return_d = {}
    if isinstance(obj, dict):
        for k in obj:
            if in_key == k:
                return_d[k] = in_val
            else:
                return_d[k] = obj[k]
        return return_d
    else:
        return obj

json_dump = json.dumps(in_dict)
json_load = json.loads(json_dump, object_hook=val_hook)

参考文献

【讨论】:

  • 我觉得这有点莫名其妙。为什么要为这么简单的事情求助于这样的黑客?理智的解决方案:def func(d): for k, v in d.items(): if in_key == k: d[k] = in_val; elif isinstance(v, dict): func(v)。根本不需要使用json
  • 你完全正确,因为我把开头的问题写成“嵌套字典”的愚蠢方式。我的意思是有效的 json,所以“嵌套的 dict/array”。我编辑了原始问题以反映我真正追求的内容。对不起。很好的提示,谢谢!
猜你喜欢
  • 2012-03-24
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
相关资源
最近更新 更多