Кастомный десонализатор GSON
У меня есть несколько ответов API в этом формате:
{
status: "OK",
error: null,
data: [
]
}
Где поле "данные" отличается (один элемент и список элементов)... Итак, я написал собственный десериализатор:
public class CustomDeserializer<T> implements JsonDeserializer<ServerResponse<T>> {
private Type t;
public CustomDeserializer() {
}
public CustomDeserializer(Type t) {
this.t = t;
}
@Override
public ServerResponse<T> deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
Gson gson = new Gson();
ServerResponse<T> serverResponse = new ServerResponse<>();
serverResponse.setError(gson.fromJson(je.getAsJsonObject(), Error.class));
serverResponse.setStatus(gson.fromJson(je.getAsJsonObject(), ResponseStatus.class));
if (je.getAsJsonObject().get("data").isJsonArray()) {
JsonArray arr = je.getAsJsonObject().getAsJsonArray("data");
T[] a = (T[]) new Object[arr.size()];
for (int i = 0; i < arr.size(); i++) {
a[i] = gson.fromJson(arr.get(i), t);
}
((ServerResponse<List<T>>) serverResponse).setData(Arrays.asList(a));
return serverResponse;
} else {
T data = gson.fromJson(je.getAsJsonObject().get("data"), t);
serverResponse.setData(data);
return serverResponse;
}
}
}
Настройка Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapter(ServerResponse.class, new CustomDeserializer<Category>(Category.class))
.registerTypeAdapter(ServerResponse.class, new CustomDeserializer<City>(City.class))
.registerTypeAdapter(ServerResponse.class, new CustomDeserializer<Business>(Business.class))
.registerTypeAdapter(ServerResponse.class, new CustomDeserializer<BusinessListItem>(BusinessListItem.class))
.create();
Но когда приходит ответ... Десериализатор десериализует его не в том классе...
Есть ли у вас какие-либо предложения, как я могу решить эту проблему?
1 ответ
Это зависит от вашей структуры данных. Если у вас есть
public static class ServerResponse<T>{
private Error error;
private ResponseStatus status;
private List<T> data;
// getters, setters , tostring
}
Вы можете использовать этот универсальный десериализатор:
public static class CustomDeserializer implements JsonDeserializer<ServerResponse> {
@Override
public ServerResponse deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
JsonObject jObject = (JsonObject) je;
ServerResponse serverResponse = new ServerResponse();
JsonElement dataElement = jObject.get("data");
JsonElement errorElement = jObject.get("error");
JsonElement statusElement = jObject.get("status");
Error error = jdc.deserialize(errorElement, Error.class);
ResponseStatus status = jdc.deserialize(statusElement, ResponseStatus.class);
ArrayList dataObj;
if (dataElement.isJsonArray()) {
JsonArray array = dataElement.getAsJsonArray();
Type listT = ParameterizedTypeImpl.make(List.class, new Type[]{t}, null);
dataObj = jdc.deserialize(array, listT);
} else {
dataObj = new ArrayList();
dataObj.add(jdc.deserialize(dataElement, t));
}
serverResponse.setError(error);
serverResponse.setStatus(status);
serverResponse.setData(dataObj);
return serverResponse;
}
}
Случай использования:
Gson gson = new GsonBuilder().registerTypeAdapter(ServerResponse.class,new CustomDeserializer()).create();
ServerResponse<String> resp = gson.fromJson(jsonString, new TypeToken<ServerResponse<String>>() {}.getType());
Редактировать пост-обновление после десериализации JSON в класс с общим аргументом, используя GSON или Jackson