如何处理嵌套JSON并实现占位符查找替换(解决非字符串类型值报错问题)
解决占位符替换时的类型错误问题
这个问题的核心在于你没有区分两种不同的占位符场景,同时原代码的参数存在性判断有逻辑漏洞。下面是修复后的完整代码,以及关键修改点的解释:
修复后的代码
import re START_DELIMITER = '<' END_DELIMITER = '>' def format_params(d, params_lookup): if isinstance(d, list): return [format_params(item, params_lookup) for item in d] if isinstance(d, dict): return {key: format_params(value, params_lookup) for key, value in d.items()} if isinstance(d, str): # 先判断是否是完整的占位符(比如"<year>") full_match = re.fullmatch( f"{re.escape(START_DELIMITER)}(\\w+){re.escape(END_DELIMITER)}", d ) if full_match: param = full_match.group(1) if param not in params_lookup: raise Exception(f"Parameter {d} is not found in the mapping") # 直接返回原类型的值,不转字符串 return params_lookup[param] # 再处理字符串中嵌入的占位符(比如"<population> million") partial_matches = re.findall( f"{re.escape(START_DELIMITER)}(\\w+){re.escape(END_DELIMITER)}", d ) if partial_matches: result = d for param in partial_matches: if param not in params_lookup: raise Exception(f"Parameter {START_DELIMITER}{param}{END_DELIMITER} is not found in the mapping") # 把 lookup 值转成字符串后再替换 result = result.replace( f"{START_DELIMITER}{param}{END_DELIMITER}", str(params_lookup[param]) ) return result # 没有占位符的字符串直接返回 return d # 非字符串类型直接返回 return d # 测试用例 params_lookup = {"population":47, "year":2022, "valid":True, "end":"colls", "num":23, "items":"more"} record = {"country":"zzzx", "metrics":{"population":"<population> million", "currency":"Euro", "year":"<year>"}, "valid":"<valid>", "others":["<num>", 2, 3], "name":"<items>"} print(format_params(record, params_lookup))
关键修改点说明
修复参数存在性判断逻辑
原代码用if not params_lookup.get(param)会把False、0这类合法的参数值误判为"不存在",改成if param not in params_lookup才能准确判断参数是否在查找字典中。区分两种占位符场景
- 完整占位符:如果字符串本身就是一个完整的占位符(比如
<year>),直接返回查找字典中的原类型值(比如整数2022、布尔值True),不需要转成字符串。 - 嵌入型占位符:如果字符串中包含占位符但不是整个字符串都是(比如
<population> million),则把查找值转成字符串后再执行替换,保证replace()方法不会报错。
- 完整占位符:如果字符串本身就是一个完整的占位符(比如
使用
re.escape处理分隔符
虽然当前的分隔符<和>不是正则特殊字符,但用re.escape包裹可以避免未来修改分隔符时出现正则语法错误,是更健壮的写法。
运行这段代码后,你会得到完全符合预期的结果:
{ "country": "zzzx", "metrics": { "population": "47 million", "currency": "Euro", "year": 2022 }, "valid": True, "others": [23, 2, 3], "name": "more" }
内容的提问来源于stack exchange,提问作者kites
相关产品推荐
相关产品推荐

