【问题标题】:Deserializing JSON with multiple types in one field在一个字段中反序列化具有多种类型的 JSON
【发布时间】:2012-12-03 04:57:04
【问题描述】:

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

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

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

任何一种情况都可以与特定类型的一个设置器(字符串或自定义响应类)一起正常工作,但是当我放入我的实体 bean 覆盖设置器以能够处理这两种情况时,会引发异常:

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 中的设置器:

@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;
}

【问题讨论】:

  • 我推荐你使用 Jackson 解析器来处理 JSON 对象的服务器端操作
  • 我在客户端工作,服务器不是我的事 :(

标签: java json jackson resttemplate


【解决方案1】:

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

这是一个例子:

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<Response>  {
  @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

}

【讨论】:

  • 我同意,我正在尝试以类似的方式进行操作,正如我所写(使用 @JsonDeserialize(using = ResponseDataDeserializer.class)),所以如果我让它运行,我会标记你的答案:)
  • 好的,它就是这样工作的,工作代码附加到原始问题。谢谢。
猜你喜欢
  • 2021-01-21
  • 2016-11-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 2011-09-04
  • 2017-11-15
相关资源
最近更新 更多