12

JSON (Jackson 1.9.11 および RestTemplate 1.0.1 を使用) をデシリアライズしたいと思います。たとえば、1 つのフィールドがより多くの型の意味を持つ場合があります。

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

また

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

いずれかのケースが特定のタイプ (文字列またはカスタム Response クラス) の 1 つのセッターで正しく機能しますが、両方のケースを処理できるようにエンティティ 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]

私は3つの解決策について考えていましたが、どれもうまくいきませんでした:

  • 文字列セッターのみを使用し、内部で ObjectMapper を使用してその文字列をアンマーシャリングしますが、それが「エラー」と等しくない場合、その JS 配列が来ると文字列ではないため、文字列セッターは使用されません:(.
  • 独自の JsonDeserializer 拡張機能で多相型処理 (@JsonTypeInfo 注釈) を使用します。これを理解し、実装しようとしています。
  • HttpMessageConverter のリストを作成し、使用できるすべてのメッセージ コンバーターの中に入れます。しかし、MappingJacksonHttpMessageConverter のみが使用されるため、この手順は不要だと思います。

編集:現在の仕組み

エンティティ Bean のセッター:

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

ResponseDeserializer の Deserialize メソッド:

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

1 に答える 1

12

これを実現する唯一の方法は、カスタム デシリアライザーを使用することです。

次に例を示します。

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

}
于 2012-12-15T11:28:50.987 に答える