如何构建含多个可选捕获组的Regex以解析结构不一致的JSON
适配结构多变JSON的正则捕获方案
问题场景
需要解析每行结构不一致的JSON数据,提取指定字段(company、address1、country、name),即使部分字段缺失也要返回空值占位。示例JSON如下:
{"company": 123, "irrelevant": "nonsense", "address": {"address1": "123 London Road", "country": "GB"}} {"company": 456, "irrelevant": "nonsense", "country": "GB", "Name": "Mary"} {"company": 789, "irrelevant": "nonsense", "address": {"address1": "123 Paris Road", "country": "FR", "Name": "Joe"}} {"company": 444}
期望输出每个行的捕获结果:
groups from row 1: ["123", "123 London Road", "GB", ""] groups from row 2: ["456", "", "GB", "Mary"] groups from row 3: ["789", "123 Paris Road", "FR", "Joe"] groups from row 4: ["444", "", "", ""]
原有问题
最初的正则仅适配所有字段都存在的情况,改为可选捕获组后,因贪婪匹配(.+)会直接吞噬整个字符串,导致后续可选组无法匹配到内容:
(?<=company": )(\d+).+("address1": ".+?")?.+("country": ".+?")?.+("name": ".+?")?
解决方案
改用非贪婪匹配替代贪婪匹配,为每个目标字段独立编写可选捕获组,同时开启不区分大小写匹配适配字段名的大小写差异:
最终正则表达式
(?i)(?<=company": )(\d+)(?:.*?"address1":\s*"([^"]*)")?(?:.*?"country":\s*"([^"]*)")?(?:.*?"name":\s*"([^"]*)")?.*
正则解析
(?i):开启不区分大小写模式,兼容Name和name这类大小写差异(?<=company": )(\d+):精准捕获company对应的数字值(?:.*?"address1":\s*"([^"]*)")?:可选捕获组,非贪婪匹配到address1字段并提取其值;字段不存在时返回空(?:.*?"country":\s*"([^"]*)")?:同理处理country字段,无论字段在顶层还是嵌套的address对象中都能匹配(?:.*?"name":\s*"([^"]*)")?:同理处理name字段.*:匹配剩余无关内容,不影响核心字段的捕获
扩展说明
如果需要添加更多字段,只需按照以下格式追加可选捕获组即可:
(?:.*?"目标字段名":\s*"([^"]*)")?
注意:若JSON字符串中包含转义双引号(如
"address1": "123 \"Main\" Street"),该正则会失效,这种场景建议使用专业JSON解析库而非正则。
内容的提问来源于stack exchange,提问作者NDJ2212
相关产品推荐
相关产品推荐

