Jackson反序列化外层包裹额外引号的JSON对象报错如何配置解决
问题原因
你遇到的报错是因为外层额外包裹的引号会让Jackson把整个内容识别为字符串类型的值,而不是JSON对象,默认没有将字符串转为Trade实例的规则,因此抛出MismatchedInputException异常。
可行解决方案
以下几种方式都可以实现兼容处理,无需手动预处理原始字符串:
方案1:为目标类增加字符串参数构造函数(改动最小)
异常提示已经明确说明缺少字符串入参的构造方法,直接给Trade类补充对应构造函数即可,无需修改全局配置:
@JsonCreator public Trade(String jsonStr) throws JsonProcessingException { // 建议复用全局ObjectMapper实例,避免重复创建对象 ObjectMapper innerMapper = new ObjectMapper(); Trade tempTrade = innerMapper.readValue(jsonStr, Trade.class); this.value = tempTrade.getValue(); this.currency = tempTrade.getCurrency(); }
该方案适配性强,正常结构的JSON和外层带引号的JSON都可以正常解析。
方案2:全局注册自定义反序列化器(无需修改业务类)
如果需要兼容多个业务类,不想逐个修改类定义,可以自定义通用反序列化器,注册到ObjectMapper全局生效:
第一步:编写通用反序列化器
public class WrappedJsonDeserializer<T> extends StdDeserializer<T> { private final Class<T> targetClass; public WrappedJsonDeserializer(Class<T> targetClass) { super(targetClass); this.targetClass = targetClass; } @Override public T deserialize(JsonParser parser, DeserializationContext context) throws IOException { // 检测当前输入是否为字符串类型 if (parser.currentToken() == JsonToken.VALUE_STRING) { // 取出字符串内容做二次反序列化 String innerJson = parser.getValueAsString(); return parser.getCodec().readValue(innerJson, targetClass); } // 正常JSON结构直接走默认反序列化逻辑 return parser.getCodec().readValue(parser, targetClass); } }
第二步:注册到ObjectMapper
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 为需要兼容的业务类注册反序列化器,可批量添加多个类的配置 module.addDeserializer(Trade.class, new WrappedJsonDeserializer<>(Trade.class)); mapper.registerModule(module);
配置完成后,直接调用原有反序列化逻辑即可兼容两种格式的输入。
方案3:临时手动二次反序列化(最灵活,无需修改配置)
如果只是偶发场景,不想改动全局配置和类定义,可以分两步处理:
// 第一步先把外层包裹的内容读取为内部JSON字符串 String innerJson = mapper.readValue(jsonString2, String.class); // 第二步把内部JSON字符串反序列化为目标对象 Trade res2 = mapper.readValue(innerJson, Trade.class);
内容的提问来源于stack exchange,提问作者curious_soul
相关产品推荐
相关产品推荐

