Использование общего типа с Gson
Я пытаюсь создать общий класс для использования с Google Gson. Я создал класс GsonJsonConverterImplementation<T>
. Этот класс имеет следующий метод:
public T deserialize(String jsonString) {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("MM/dd/yy HH:mm:ss");
Gson gson = builder.create();
return gson.fromJson(jsonString, T); // T.class etc. what goes here
}
Цель состоит в том, что этот метод должен иметь возможность работать с любым типом, с которым я установил свой GsonJsonConverterImplementation для работы. К сожалению, gson.fromJson(jsonString, T)
не работает и не использует T.class
вместо T. Я уверен, что проблема связана с отсутствием понимания типов Java-типов. Каков правильный способ использования общего с Gson?
Изменить
Используя ответ Криса Я бы предположил, что это должно сработать. К сожалению, clazz нельзя использовать таким образом и вызывает ошибку компилятора. Каковы мои варианты работы с коллекцией и общий тип с Gson?
public List<T> deserializeList(String jsonString, Class<T> clazz) {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("MM/dd/yy HH:mm:ss");
Gson gson = builder.create();
Type listType = new TypeToken<clazz>(){}.getType(); // compiler error
return gson.fromJson(jsonString, listType);
}
Ответы
Ответ 1
Самый простой подход к тому, что вы пытаетесь, - это определить тип класса, который должен быть возвращен в самой сигнатуре метода. Вы можете сделать это, либо передав экземпляр "T" методу, либо класс возвращаемого значения. Второй подход более типичен в тех случаях, когда вы ожидаете генерировать возвращаемое значение. Вот пример такого подхода с использованием Gson:
public <T> T deserialize(String jsonString, Class<T> clazz) {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("MM/dd/yy HH:mm:ss");
Gson gson = builder.create();
return gson.fromJson(jsonString, clazz);
}
Использование:
MyClass mc = deserialize(jsonString, MyClass.class);
Ответ 2
Чтобы получить тип времени выполнения List<T>
, учитывая класс T
, он сосать, потому что JDK не думал, что нам это нужно, поэтому нет поддержки. Вы можете подклассом ParameterizedType
, но это действительно отстой.
Type typeListT = new ParameterizedType()
{
public Type[] getActualTypeArguments()
{
return new Type[]{clazz};
}
public Type getRawType()
{
return List.class;
}
public Type getOwnerType()
{
return null;
}
public boolean equals(Object obj)
{
// must implement equals per spec. this sucks
}
public int hashCode()
{
// this blows! Java forgot to specific it!
// since we override equals, we should override hashCode
// we have no idea what value should be returned here!
// note we are co-existing with other ParameterizedType impls
}
};
Ответ 3
Я использую этот метод для чтения и записи объекта с использованием GSON.
public static <T> void saveAnyTypeOfObject(String key, T value){
Gson gson = new Gson();
String json = gson.toJson(value);
SharedPref.save(key, json);
}
//Type listType = new TypeToken<YourClass>(){}.getType();
public static <T> T readAnyTypeOfObject(String key, Type tt) {
Gson gson = new Gson();
String json = SharedPref.read(key, "{}");
T obj = gson.fromJson(json, tt);
return obj;
}
прочитайте его как
TypeToken<YourClassName> typeToken= new TypeToken<YourClassName>() {};
YourClassName yourClassName = ListSharedPref.readAnyTypeOfObject("keyForSavingClass", typeToken.getType());
и сохраните его как
YourClassName yourClassName = gson.fromJson(objJsonObject.toString(),YourClassName.class);
ListSharedPref.saveAnyTypeOfObject("keyForSavingClass",yourClassName);