多层次结构中的python json配置变量密钥替换

2024-09-26 22:11:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我计划对配置文件使用json,目前我有一个这样的配置

{
  "settings": {
    "general": "root",
    "folder": "folder_test"
  },
  "TEST1": {
    "dataone": "xyz",
    "testing": {
      "a": "$general/$folder/test.png",
      "b": "$general/$folder/test.png"
    },
    "SOMELIST": [
      "$general/$folder/test.png",
      "$general/$folder/test.png"
    ]
  },
  "TEST2": {
    "dataone": "xyz",
    "testing": {
      "a": "$general/$folder/test.png",
      "b": "$general/$folder/test.png"
    },
    "something": {
        "test_data": {
          tester: {
            "abc": "$general/$folder/test.png",
            "zxv": "$general/$folder/test.png"
          }
        }
    }
  }
}

我的目的是让settings部分填充静态路径,如root和foldername等,并让config的其余部分贯穿整个config层次结构,以将设置用作变量。这是为了路径和文件夹的目的,如果根目录或新文件夹更改/添加,我在以后维护时不会有任何问题

我希望配置能够在以后的层次结构的任何级别中使用所有设置变量,即使在将来添加了新的级别

到目前为止,我只能循环一个级别,但不确定如何访问多个级别

for k, v in config.items():
    for key in config.keys():
        if key in v:
            config[k] = v.replace("$" + key, config[key])

在stackoverflow的另一个主题中找到了这个,但这只是一个级别。我不知道如何建立一个通用的,可以在这里包括多个级别


Tags: keyintest路径目的configsettingspng
1条回答
网友
1楼 · 发布于 2024-09-26 22:11:56

您是否考虑过在将其解析为JSON之前只替换变量,而不是单独替换每个项目的变量?这样可以减少内存/计算成本,而且应该更容易

config = ""
with open("config.json") as f:
    config = f.read().replace("$variable", "stackoverflow")

parsed_config = your_parser(config)

编辑:编写了一个递归替换函数。我希望你能读到它&;从中学习

import json

call_counter = 0

def replace_string(value: str, template_vars: {}) -> object:
    """
    Replaces template strings in value, by the values in template_vars. 
    """
    for template, newValue in template_vars.items():
        value = value.replace("${}".format(template), newValue)

    return value


def replace_recursive(json_obj: object, template_vars: {}) -> {}:
    """
    Recursively unpacks and replaces items in a multi-dimensional dict/list/item json object.
    """
    # For each item at this level 
    for key, value in json_obj.items():
        # If the value is a string, replace it
        if isinstance(value, str):
            json_obj[key] = replace_string(value, template_vars)        

        # If the item is a list, we need to do something for each value
        elif isinstance(value, list):
            # Enumate unpacks an index with each value
            for index, item in enumerate(value):
                # If it's a string, we can replace it 
                if isinstance(item, str):
                    value[index] = replace_string(item, template_vars)
                # If it's not, we need to do more work. 
                else:
                    value[index] = replace_recursive(item, template_vars)

        # If it's a dict, use this function again to unpack/replace the values
        else:
            json_obj[key] = replace_recursive(value, template_vars)

    return json_obj

if __name__ == "__main__":

    template_vars = {}

    # Read our file
    with open("example.json") as f:
        json = json.load(f)

    # Read our settings
    template_vars = json['settings']

    # Drop our settings block (don't if you don't want to)
    json.pop('settings')

    json = replace_recursive(json, template_vars)
    print(json)

这使用了相当多的函数调用。此配置没有问题,但另一个配置可能有问题

相关问题 更多 >

    热门问题