遗留类JSON格式数据转换的正则优化及Python高效读取方案咨询
遗留类JSON格式数据转换的正则优化及Python高效读取方案咨询
嘿,针对你遇到的这个遗留类JSON格式转换问题,我来分享一些实用的优化思路和靠谱方案吧~
首先得说说你当前用的正则替换可能存在的几个小坑:
- 第一个匹配数值的正则
([\w]{1,}) = ([\d\.]{1,},?),没法处理负数(比如-2.5),而且如果数值行尾带逗号,替换后可能会导致JSON语法报错 - 第二个匹配字符串的正则
([\w]{1,}) = ([\w]{1,}),完全搞不定带特殊字符、转义符或者引号的字符串(比如你示例里第6行的"a\b"),而且只能匹配纯字母数字的字符串,局限性太大 - 正则本身对嵌套结构的支持很差,万一你的数据里有更深层次的嵌套,很容易出现匹配错位的情况
优化后的正则替换方案
如果还是想用正则快速适配,我建议调整成下面这几组正则(一定要按顺序执行哦):
- 先给所有键加引号,把等号换成冒号
- 正则:
(\w+)\s*=\s*(?!\[|\{) - 替换为:
"$1": - 作用:避开列表和对象开头的等号,先把普通键值对的格式转成JSON风格,避免后续匹配干扰
- 正则:
- 处理数值类型的值
- 正则:
:\s*([-+]?\d+\.?\d*) - 替换为:
: $1 - 作用:确保正负整数、浮点数都能正确保留,不需要额外加引号
- 正则:
- 给纯字母数字的字符串值加引号
- 正则:
:\s*(\w+)(?=,|\s*$) - 替换为:
: "$1" - 作用:覆盖像
hello、V1D这类简单字符串的转换
- 正则:
- 处理带HTML转义引号的特殊字符串
- 正则:
:\s*(".*?") - 替换为:
: $1 - 作用:先保留这类特殊字符串,后续可以用Python的
html.unescape()把"转成普通双引号
- 正则:
更可靠的非正则方案:用解析库处理
其实正则处理这种半结构化数据始终有风险,尤其是数据格式复杂的时候,更推荐用专门的解析库,比如pyparsing,它可以自定义语法规则来精准解析你的遗留格式,示例代码如下:
from pyparsing import Word, nums, alphas, Literal, Forward, Group, Dict, Optional, OneOrMore, Regex import html # 定义基础元素规则 number = Regex(r"[-+]?\d+\.?\d*") # 匹配带HTML转义引号的字符串和普通字母数字字符串 string = Regex(r"".*?"") | Word(alphas + nums + "_") key = Word(alphas + nums + "_") equals = Literal("=").suppress() # 忽略等号 comma = Literal(",").suppress() # 忽略逗号 # 定义嵌套结构(先声明后定义,支持递归) object_expr = Forward() list_expr = Forward() # 定义值的可能类型 value = number | string | list_expr | object_expr # 定义键值对结构 key_value = Group(key + equals + value + Optional(comma)) # 定义对象结构 object_expr << Literal("{").suppress() + Dict(OneOrMore(key_value)) + Literal("}").suppress() # 定义列表结构 list_expr << Literal("[").suppress() + OneOrMore(value + Optional(comma)) + Literal("]").suppress() # 解析你的示例数据 data_str = """{ base = { attributeNumericName = V1D, attributeName = hello, attributeFloat = 1.0, attributeQuotes = "a\b", canContainLists = [ 1.0, 2.0 ], canContainStackedData = [ { stackedAttribute = 1.0 } ] } }""" parsed_data = object_expr.parseString(data_str).asDict() # 处理HTML转义的引号 def unescape_strings(obj): if isinstance(obj, dict): for k, v in obj.items(): obj[k] = unescape_strings(v) elif isinstance(obj, list): for i in range(len(obj)): obj[i] = unescape_strings(obj[i]) elif isinstance(obj, str) and """ in obj: return html.unescape(obj) return obj parsed_data = unescape_strings(parsed_data) print(parsed_data)
这个方法比正则灵活太多,能轻松处理各种嵌套结构和特殊字符串,后续维护也更方便。
最后提个效率小建议
如果你的数据量很大,追求极致读取效率的话,可以先把转换后的合法JSON写入临时文件,再用Python内置的json.load()来读取,比直接在内存里转换后解析更稳定哦~
备注:内容来源于stack exchange,提问作者Sybren Zwetsloot
相关产品推荐
相关产品推荐

