繁体   English   中英

Python替换未知结构JSON文件中的值

[英]Python replace values in unknown structure JSON file

假设我有一个 JSON 文件,它的结构要么未知,要么可能会随着时间的推移而改变——我想用我在 Python 中选择的字符串替换“REPLACE_ME”的所有值。

我发现的一切都假设我知道结构。 例如,我可以使用json.load读取 JSON 并遍历字典进行替换,然后将其写回。 这假设我知道密钥名称、结构等。

如何用其他东西替换 JSON 文件中的所有给定字符串值?

此函数递归地将所有等于original值的字符串替换为new值。

此函数适用于 python 结构 - 但当然你可以在 json 文件上使用它 - 通过使用json.load

它不会替换字典中的键 - 只是值。

def nested_replace( structure, original, new ):
    if type(structure) == list:
        return [nested_replace( item, original, new) for item in structure]

    if type(structure) == dict:
        return {key : nested_replace(value, original, new)
                     for key, value in structure.items() }

    if structure == original:
        return new
    else:
        return structure

d = [ 'replace', {'key1': 'replace', 'key2': ['replace', 'don\'t replace'] } ]
new_d = nested_replace(d, 'replace', 'now replaced')
print(new_d)
['now replaced', {'key1': 'now replaced', 'key2': ['now replaced', "don't replace"]}]

我认为如果你想替换任何用引号括起来的键或值,没有太大的风险(因为引号在 json 中被转义,除非它们是字符串分隔符的一部分)。

我会转储结构,执行str.replace (带双引号),然后再次解析:

import json

d = { 'foo': {'bar' : 'hello'}}

d = json.loads(json.dumps(d).replace('"hello"','"hi"'))

print(d)

结果:

{'foo': {'bar': 'hi'}}

我不会冒险替换部分字符串或没有引号的字符串,因为它可能会更改文件的其他部分。 我想不出一个例子,替换没有双引号的字符串可以改变其他东西。

有一些“干净”的解决方案,比如从JSON 文件中的替换值适应可以嵌套 n 级的键,但值得付出努力吗? 取决于您的要求。

为什么不直接修改文件而不是将其视为 JSON?

with open('filepath') as f:
    lines = f.readlines()
for line in lines:
    line = line.replace('REPLACE_ME', 'whatever')
    with open('filepath_new', 'a') as f:
        f.write(line)

好吧,这取决于,如果您想使用相同的字符串放置所有标题为“REPLACE_ME”的字符串,您可以使用它。 for 循环遍历字典中的所有键,然后您可以使用这些键来选择字典中的每个值。 如果它等于您的替换字符串,它将用您想要的字符串替换它。

search_string = "REPLACE_ME"
replacement = "SOME STRING"
test = {"test1":"REPLACE_ME", "test2":"REPLACE_ME", "test3":"REPLACE_ME", "test4":"REPLACE_ME","test5":{"test6":"REPLACE_ME"}}


def replace_nested(test):

    for key,value in test.items():

        if type(value) is dict:
            replace_nested(value)
        else:
            if value==search_string:
                test[key] = replacement


replace_nested(test)
print(test)

可以将 JSON 文件加载到字典中并通过它递归查找正确的值,但这是不必要的肌肉弯曲。

最好的方法是简单地将文件视为字符串并以这种方式进行替换。

json_file = 'my_file.json'
with open(json_file) as f:
    file_data = f.read()

file_data = file_data.replace('REPLACE_ME', 'new string')
<...>

with open(json_file, 'w') as f:
    f.write(file_data)

json_data = json.loads(file_data)

从这里可以重写文件,您可以继续使用json_data作为 dict。

为了动态解决这个问题,我已经获得了使用相同的json文件来声明我们要替换的变量。

JSON 文件:

{
"properties": {
"property_1": "value1",
"property_2": "value2"
},
"json_file_content": {
   "key_to_find": "{{property_1}} is my value"
   "dict1":{
       "key_to_find": "{{property_2}} is my other value"
   }
}

Python 代码(参考JSON 文件中可以嵌套 n 级的键的替换值):

import json    
def fixup(self, a_dict:dict, k:str, subst_dict:dict) -> dict:
"""
function inspired by another answers linked below
""" 
    for key in a_dict.keys():
        if key == k:
            for s_k, s_v in subst_dict.items():
                a_dict[key] = a_dict[key].replace("{{"+s_k+"}}",s_v)
        elif type(a_dict[key]) is dict:
            fixup(a_dict[key], k, subst_dict)
# ...
file_path = "my/file/path"
if path.exists(file_path):
   with open(file_path, 'rt') as f:
   json_dict = json.load(f)
   fixup(json_dict ["json_file_content"],"key_to_find",json_dict ["properties"])
   print(json_dict) # json with variables resolved
else:
   print("file not found")

希望能帮助到你

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM