「 Jackson動的プロパティ名」という質問はすでに見ましたが、私の質問には実際には答えていません。
私はこのようなものをデシリアライズしたい:
public class Response<T> {
private String status;
private Error error;
private T data;
}
ただし、異なるサービスが存在し、いくつかの異なるデータで同じ構造を返すため、データには異なる名前を付けることができます。たとえば、'user' と 'contract' :
{
response: {
status: "success",
user: {
...
}
}
}
また
{
response: {
status: "failure",
error : {
code : 212,
message : "Unable to retrieve contract"
}
contract: {
...
}
}
}
次のように応答オブジェクトを一般化したいと思います。
public class UserResponse extends Response<User> {}
私は次のことを試しましたが、それが私のユースケースであるかどうか、または良い方法で使用しないかどうかはわかりません:
@JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.CLASS)
@JsonSubTypes({@Type(value = User.class, name = "user"),
@Type(value = Contract.class, name = "contract")})
最後に、カスタム デシリアライザーを作成しました。それは動作しますが、私は満足していません:
public class ResponseDeserializer extends JsonDeserializer<Response> {
@Override
public Response deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Response responseData = new Response();
Object data = null;
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
if ("contract".equals(propName)) {
data = mapper.readValue(jp, Contract.class);
} else if ("user".equals(propName)) {
data = mapper.readValue(jp, User.class);
} else if ("status".equals(propName)) {
responseData.setStatus(jp.getText());
} else if ("error".equals(propName)) {
responseData.setError(mapper.readValue(jp, com.ingdirect.dg.business.object.community.api.common.Error.class));
}
}
if (data instanceof Contract) {
Response<Contract> response = new Response<Ranking>(responseData);
return response;
}
if (data instanceof User) {
Response<User> response = new Response<User>(responseData);
return response;
}
// in all other cases, the type is not yet managed, add it when needed
throw new JsonParseException("Cannot parse this Response", jp.getCurrentLocation());
}
}
注釈でこれをきれいにするアイデアはありますか? 前もって感謝します !