#java #json #jackson #deserialization #json-deserialization
#java #json #джексон #десериализация #json-десериализация
Вопрос:
У меня есть следующие классы:
public class Result<T> {
public int code;
public Object meta;
public T data;
}
public class User {
public int id;
public String name;
}
public class Error {
public String field;
public String message;
}
Я хочу десериализовать JSON
полезную нагрузку на основе code
поля. Если code >= 10
, верните Result<ArrayList<Error>>
, в противном случае верните Result<User>
В настоящее время я сначала сопоставляю JSON
с Result<Object>
, затем проверяю code
поле. На основе этого значения я создаю второе сопоставление с желаемым объектом.
ObjectMapper mapper = new ObjectMapper();
Result<Object> tempResult = mapper.readValue(json, new TypeReference<Result<Object>>() {});
if (tempResult.code < 10) {
Result<User> result = mapper.readValue(json, new TypeReference<Result<User>>() {});
return resu<
} else {
Result<ArrayList<Error>> result = mapper.readValue(json, new TypeReference<Result<ArrayList<Error>>>() {});
return resu<
}
Есть ли элегантный способ сделать это без десериализации 2 раза?
Ответ №1:
Вам необходимо реализовать пользовательский TypeIdResolver
:
class UserTypeIdResolverBase extends TypeIdResolverBase {
@Override
public String idFromValue(Object value) {
throw new IllegalStateException("Not implemented!");
}
@Override
public String idFromValueAndType(Object value, Class<?> suggestedType) {
throw new IllegalStateException("Not implemented!");
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
@Override
public JavaType typeFromId(DatabindContext context, String id) {
if (Integer.parseInt(id) < 10) {
return context.getTypeFactory().constructType(new TypeReference<Result<User>>() {});
}
return context.getTypeFactory().constructType(new TypeReference<Result<List<Error>>>() {});
}
}
и объявите его для Result
класса:
@JsonTypeInfo(property = "code", use = JsonTypeInfo.Id.CUSTOM, visible = true)
@JsonTypeIdResolver(UserTypeIdResolverBase.class)
class Result<T>