[英]Json dynamic deserialization with jackson
我已經看過“ 傑克遜動態屬性名稱 ”的問題,但它並沒有真正回答我的問題。
我想反序列化這樣的事情:
public class Response<T> {
private String status;
private Error error;
private T data;
}
但是數據可以具有不同的名稱,因為存在不同的服務並且返回具有不同數據的相同結構。 例如'用戶'和'合同':
{
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());
}
}
有沒有想過用注釋做這個干凈? 提前致謝 !
Jackson框架為動態類型提供內置支持。
//Base type
@JsonTypeInfo(property = "type", use = Id.NAME)
@JsonSubTypes({ @Type(ValidResponse.class),
@Type(InvalidResponse.class)
})
public abstract class Response<T> {
}
//Concrete type 1
public class ValidResponse extends Response<T>{
}
//Concrete type 2
public class InvalidResponse extends Response<T>{
}
main {
ObjectMapper mapper = new ObjectMapper();
//Now serialize
ValidResponse response = (ValidResponse)(mapper.readValue(jsonString, Response.class));
//Deserialize
String jsonString = mapper.writeValueAsString(response);
}
你有沒有嘗試過:
public class AnyResponse {
private String status;
private Error error;
private Contract contract;
private User user;
// And all other possibilities.
}
// ...
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
這應該填寫JSON中出現的任何對象,並將其余部分保留為null。
然后,您可以使用相關對象填寫響應。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.