Кастомный десонализатор 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

Другие вопросы по тегам