SpringBoot接收非标准类JSON数据时如何实现Entity实体映射
非标准类JSON格式请求解析方案
你收到的请求数据属于类JSON非标准格式,和标准JSON的差异为:键无双引号、键值间用=代替:、普通字符串值无双引号,原始数据结构如下:
a= { b= { b1=null, b2=1, b3=null, b4=null, b5=null }, c={ c1=null, c2=1, c3=nfsaf }, ds= [ { d1=dsdsadad, d2=null, d3=null }, {...} ] }
直接使用Jackson、Gson默认配置解析会报错,不需要直接上全量正则匹配,按优先级选择以下方案即可:
方案1:轻量预处理转标准JSON(无额外依赖,推荐优先使用)
不需要替换现有JSON解析框架,只需要在解析前做规则固定的字符串替换,把非标准格式转为标准JSON后,直接用已有的Jackson/Gson映射为Entity即可,替换顺序和逻辑如下:
- 第一步:匹配所有键位的
单词字符+=模式,替换为"键名":,给所有键加双引号,同时把等号换成JSON标准的冒号 - 第二步:匹配所有值位置的内容,跳过
null、布尔值、数字这些不需要双引号的类型,给剩下的字符串值包裹双引号
预处理代码示例:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class LooseJsonConverter { // 匹配 键= 结构 private static final Pattern KEY_PATTERN = Pattern.compile("(\\w+)\\s*="); // 匹配未加引号的值 private static final Pattern UNQUOTED_VALUE_PATTERN = Pattern.compile("(:\\s*)([a-zA-Z0-9_\\u4e00-\\u9fa5]+)(\\s*[,}\\]])"); public static String toStandardJson(String looseStr) { // 先替换所有键和等号 String afterKeyReplace = KEY_PATTERN.matcher(looseStr).replaceAll("\"$1\":"); // 再补全字符串值的双引号 Matcher valueMatcher = UNQUOTED_VALUE_PATTERN.matcher(afterKeyReplace); StringBuffer sb = new StringBuffer(); while (valueMatcher.find()) { String prefix = valueMatcher.group(1); String value = valueMatcher.group(2); String suffix = valueMatcher.group(3); // 不需要加引号的特殊值直接保留 if ("null".equals(value) || "true".equals(value) || "false".equals(value) || value.matches("-?\\d+(\\.\\d+)?")) { valueMatcher.appendReplacement(sb, Matcher.quoteReplacement(prefix + value + suffix)); } else { valueMatcher.appendReplacement(sb, Matcher.quoteReplacement(prefix + "\"" + value + "\"" + suffix)); } } valueMatcher.appendTail(sb); return sb.toString(); } }
使用时直接把原始请求字符串传入toStandardJson方法,拿到标准JSON后走原有解析逻辑即可。
注意:如果你的业务字段值里包含
,、{、}、[、]这类JSON特殊符号,需要调整值匹配的正则边界,这种场景更推荐用方案2。
方案2:宽松JSON解析库直接解析(适配复杂值场景)
如果字段值包含特殊字符,自己写正则预处理容易出现边界错误,可以直接用对非标准JSON兼容性好的库直接解析,不需要手动做格式转换。
以fastjson2为例,它默认支持无引号键、等号代替冒号、无引号字符串值的宽松解析模式,只需要引入依赖:
<dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.43</version> </dependency>
解析代码只有一行,直接映射为目标实体:
YourEntity entity = JSON.parseObject(originalRequestStr, YourEntity.class);
方案3:正则逐段提取(仅适合固定简单结构)
如果因为项目限制不能引入额外依赖、也不能做通用预处理,确实要用正则提取的话,不要写单个大正则匹配全量嵌套结构,按层级逐块提取降低出错概率:
- 第一层:匹配最外层字段对应的块,比如提取a的对象内容用正则
a\s*=\s*(\{.*\})\s*$ - 第二层:从外层块里分别提取嵌套的对象、数组块,对象匹配规则
字段名\s*=\s*(\{.*?\})(?=\s*[,}]),数组匹配规则字段名\s*=\s*(\[.*?\])(?=\s*[,}]) - 第三层:从最内层的平面对象里提取键值对,用正则
(\w+)\s*=\s*([^,}]+)逐个拿字段名和值
正则对嵌套结构的适配能力很差,如果数组/对象嵌套层级超过2层,或者字段值包含闭合符号、逗号,提取结果会出现错误,非必要不选择这个方案。
内容的提问来源于stack exchange,提问作者dongdongdong
相关产品推荐
相关产品推荐

