2016-04-12 4 views
1

У меня есть несколько ответов API в этом формате:Пользовательские GSON deserialiser

{ 
    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(); 

Но когда приходит ответ ... десериализатор десериализует его в неправильном классе ...

Есть ли у вас какие-либо предложения, как я могу исправить эту проблему?

+0

Пожалуйста, покажите, как вы называете Гсоном заниматься десериализацией. – sargue

+0

@Seishin я понял, что ответ можно упростить, если вы предоставите свой тип объекта gson. А также здесь есть простой вопрос: http://stackoverflow.com/q/36614097/1032167, и, как вы можете видеть из комментариев к первому ответу, вам, вероятно, все равно придется использовать определенный тип запроса объекта, который вы хотите десериализовать. – varren

+0

@ varren, у меня есть 4 разных типа ответа для поля данных. Два из них - это списки объектов. Проблема в том, что десериализатор не знает, какой тип выбрать и десериализовать. Я добавил в вопрос настройку Gson. – Seishin

ответ

0

Это зависит от вашей структуры данных. Если у вас есть

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()); 

Редактировать после обновления после Deserializing JSON into a class with a generic argument using GSON or Jackson