在一个字段中反序列化多个类型的JSON

我想反序列化JSON(使用Jackson 1.9.11和RestTemplate 1.0.1),其中一个字段可能具有更多的类型含义,例如:

{"responseId":123,"response":"error"} 

要么

  {"responseId":123,"response":{"foo":"bar", ... }} 

一个或其他案例可以使用一个特定类型的setter(String od自定义Response类)正常工作,但是当我放入我的实体bean覆盖setter以便能够处理这两种情况时,抛出exception:

 Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [xxxx.templates.ExportResponse] and content type [application/json;charset=utf-8] 

我在考虑三种解决方案,但我没有让它们工作:

  • 只使用String setter和内部使用ObjectMapper解组该字符串,如果它不等于“error”,但是当JS Array出现时,它不是字符串所以不使用String setter :(。
  • 使用多态类型处理(@JsonTypeInfo注释)与自己的JsonDeserializer扩展 – 我仍然试图理解这一点并实现。
  • 创建HttpMessageConverter列表并放入所有消息转换器,我可以使用。 但我认为这一步是不必要的,因为只使用MappingJacksonHttpMessageConverter,我是对的吗?

编辑:它现在如何工作

实体bean中的setter:

 @JsonDeserialize(using = ResponseDeserializer.class) public void setResponse(Object responseObject) { if(responseObject instanceof Response) response = (Response) responseObject; } 

在ResponseDeserializer中反序列化方法:

 public Response deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { Response response = new Response(); if(JsonToken.START_OBJECT.equals(parser.getCurrentToken())) { ObjectMapper mapper = new ObjectMapper(); response = mapper.readValue(parser, Response.class); } else throw new JsonMappingException("Unexpected token received."); return response; } 

实现这一目标的唯一方法是使用自定义反序列化器。

这是一个例子:

 ObjectMapper mapper = new ObjectMapper(); SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null)); testModule.addDeserializer(Response.class, new ResponseJsonDeserializer()); mapper.registerModule(testModule); 

以下是如何编写(至少我将如何编写)反序列化器:

 class ResponseJsonDeserializer extends JsonDeserializer { @Override public Responsedeserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { Response response = new Response(); if(jp.getCurrentToken() == JsonToken.VALUE_STRING) { response.setError(jp.getText()); } else { // Deserialize object } return response; } } class Response { private String error; private Object otherObject; // Use the real type of your object public boolean isError() { return error != null; } // Getters and setters }