我正在构建一个JSON令牌替换器,其工作原理如下:

输入:{"greet": "hello {{name}}"}和 token {"name": "Lorenzo"}

输出:{"greet": "hello Lorenzo"}


由于我希望该函数也适用于嵌套的字典/列表,因此我使用了递归来扩展更复杂的输入的功能,例如:

输入:{"a": {"b": "x{{ppp}}z"}}和 token {"ppp": "y"})

输出:{"a": {"b": "xyz"}}

(其他测试/示例用法可用here个)


即使代码可以工作,我也不满意我当前的解决方案,因为我违反了DRY原则.

我相信我可以让我的代码更干净:有什么 idea 或建议吗?这就是我try 过的:

def __replace(input_str: str, pytokens: dict):
    for k, v in pytokens.items():
        input_str = re.sub("{{" + k + "}}", str(v), input_str)
    return input_str


def __json_replacer(pyinput, pytokens: dict):
    # TODO DRY: code is doubled, code this part again
    if isinstance(pyinput, str):
        return __replace(pyinput, pytokens)

    if isinstance(pyinput, list):
        for i in range(len(pyinput)):
            pyinput[i] = __json_replacer(pyinput[i], pytokens)
        return pyinput

    if not isinstance(pyinput, dict):
        return pyinput

    res = {}
    for k, v in pyinput.items():
        if isinstance(v, str):
            v = __replace(v, pytokens)

        if isinstance(v, list):
            for i in range(len(v)):
                v[i] = __json_replacer(v[i], pytokens)

        if isinstance(v, dict):
            v = __json_replacer(v, pytokens)

        res[k] = v

    return res

注意:该项目是开源的!如果您提供解决方案,请随意打开公关并获得积分:)GitHub project link

推荐答案

你可以缩短

if not isinstance(pyinput, dict):
    return pyinput

res = {}
for k, v in pyinput.items():
    if isinstance(v, str):
        v = __replace(v, py至kens)

    if isinstance(v, list):
        for i in range(len(v)):
            v[i] = __json_replacer(v[i], py至kens)

    if isinstance(v, dict):
        v = __json_replacer(v, py至kens)

    res[k] = v

if isinstance(pyinput, dict):
    return {k: __json_replacer(v, py至kens) for k, v in pyinput.items()}

This would then delegate the list check 至 the code above, so make a small change 至 the list handler. Change this

if isinstance(pyinput, list):
    for i in range(len(pyinput)):
        pyinput[i] = __json_replacer(pyinput[i], py至kens)
    return pyinput

if isinstance(pyinput, list):
    return [__json_replacer(v, py至kens) for v in pyinput]

Putting it 至gether

def __json_replacer(pyinput, py至kens):
    if isinstance(pyinput, str):
        return __replace(pyinput, py至kens)

    if isinstance(pyinput, list):
        return [__json_replacer(v, py至kens) for v in pyinput]

    if isinstance(pyinput, dict):
        return {k: __json_replacer(v, py至kens) for k, v in pyinput.items()}

    return pyinput

正在运行

>>> __json_replacer({"a": {"b": "x{{ppp}}z"}}, {"ppp": "y"})
# {'a': {'b': 'xyz'}}

不出所料.


我不建议将整个对象视为字符串并执行字符串替换,因为您可能最终还会在键上执行替换操作,这可能会产生意想不到的后果(例如复制或损坏键).

Python相关问答推荐

线性模型PanelOLS和statmodels OLS之间的区别

pandas DataFrame GroupBy.diff函数的意外输出

通过pandas向每个非空单元格添加子字符串

如何使用它?

OR—Tools中CP—SAT求解器的IntVar设置值

优化器的运行顺序影响PyTorch中的预测

为一个组的每个子组绘制,

Flash只从html表单中获取一个值

剪切间隔以添加特定日期

导入错误:无法导入名称';操作';

如何将数据帧中的timedelta转换为datetime

pandas fill和bfill基于另一列中的条件

Python类型提示:对于一个可以迭代的变量,我应该使用什么?

如何将返回引用的函数与pybind11绑定?

我什么时候应该使用帆布和标签?

如何使用大量常量优化代码?

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

Django更新视图未更新

是否需要依赖反转来确保呼叫方和被呼叫方之间的分离?

按列表分组到新列中