如何解析带反斜杠的JSON字符串(Spring RestTemplate场景)
问题分析
服务端返回的响应并非直接的JSON对象,而是被字符串包裹的JSON结构(即外层是带转义的字符串,内部才是ServerResponse对应的JSON)。Jackson尝试将整个外层字符串直接反序列化为ServerResponse对象,但ServerResponse没有接收字符串参数的构造方法,因此抛出反序列化异常。
可行解决方案
以下方案均无需使用string.replaceAll处理转义字符:
方案1:先获取字符串响应,再二次反序列化
直接将响应先解析为字符串,再用Jackson的ObjectMapper将字符串解析为ServerResponse对象:
// 第一步:获取原始响应字符串 ResponseEntity<String> responseEntity = restTemplate.exchange( "some url", HttpMethod.POST, requestEntity, String.class ); String responseBody = responseEntity.getBody(); // 第二步:将字符串解析为ServerResponse ObjectMapper objectMapper = new ObjectMapper(); ServerResponse serverResponse = objectMapper.readValue(responseBody, ServerResponse.class);
方案2:自定义Jackson反序列化器
给ServerResponse类添加自定义反序列化器,自动识别并处理字符串包裹的JSON结构:
- 编写自定义反序列化器:
public class ServerResponseDeserializer extends StdDeserializer<ServerResponse> { protected ServerResponseDeserializer() { super(ServerResponse.class); } @Override public ServerResponse deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 如果当前输入是字符串类型,先解析为JSON再转成对象 if (p.getCurrentToken() == JsonToken.VALUE_STRING) { String jsonStr = p.getText(); return ctxt.readValue(jsonStr, ServerResponse.class); } // 正常JSON对象场景,直接解析 return ctxt.readValue(p, ServerResponse.class); } }
- 在
ServerResponse类上添加反序列化器注解:
@Builder @AllArgsConstructor @NoArgsConstructor @JsonDeserialize(using = ServerResponseDeserializer.class) // 添加该注解 public class ServerResponse implements Serializable { private static final long serialVersionUID = xxxxxxxxxxxx; @JsonProperty("Status") public String status; }
之后即可直接使用原有的restTemplate.exchange调用方式,无需修改代码。
方案3:全局配置RestTemplate的消息转换器
通过自定义MappingJackson2HttpMessageConverter,给RestTemplate配置支持处理字符串包裹JSON的ObjectMapper:
RestTemplate restTemplate = new RestTemplate(); // 创建自定义ObjectMapper并注册反序列化器 ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(ServerResponse.class, new ServerResponseDeserializer()); objectMapper.registerModule(module); // 替换或添加消息转换器 MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(objectMapper); restTemplate.getMessageConverters().removeIf(c -> c instanceof MappingJackson2HttpMessageConverter); restTemplate.getMessageConverters().add(converter);
该方案适合全局范围内需要处理此类响应的场景,一次配置即可复用。
内容的提问来源于stack exchange,提问作者joe4java
相关产品推荐
相关产品推荐

