I want to write a generic function which deserialise a generic type List with Gson here is the code:
private <T> List<T> GetListFromFile(String filename)
{
//Read textfile
BufferedReader reader;
String data="";
try
{
reader = new BufferedReader(new FileReader(filename));
data = reader.readLine();
reader.close();
}
catch (FileNotFoundException ex)
{
}
catch (IOException ex)
{
}
if (data == null)
{
List<T> Spiel = new ArrayList<T>();
return Spiel;
}
else
{
//get list with Deserialise
Gson gson = new Gson();
List<T> something = gson.fromJson(data, new TypeToken<List<T>>(){}.getType());
return something;
}
}
But this code is not working, i get a strange structure but not a List of my type
When i'am using:
List<concreteType> something = gson.fromJson(data, new TypeToken<List<T>>(){}.getType());
i works i get a List<concreteType>
!!
But i need a generic function, how can i fix it?
Regards rubiktubik
Deserialization in the context of Gson means converting a JSON string to an equivalent Java object. In order to do the deserialization, we need a Gson object and call the function fromJson() and pass two parameters i.e. JSON string and expected java type after parsing is finished. Program output.
Gson gson = new Gson(); String json = "[ \"Adam\", \"John\", \"Mary\" ]"; Type type = new TypeToken<List<String>>(){}. getType(); List<String> members = gson. fromJson(json, type); Log. v("Members", members.
reflect. TypeToken to store the type of the generic object.
Gson is a Java library that can be used to convert Java objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object.
The approach of use TypeToken won't work.
new TypeToken<ArrayList<T>>()
is not possible because of how generics (type erasure) and reflection works. The whole TypeToken
hack works because Class#getGenericSuperclass()
does the following
Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class.
If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code.
In other words, if it sees ArrayList<T>
, that's the ParameterizedType
it will return and you won't be able to extract the compile time value that the type variable T
would have had.
Type
and ParameterizedType
are both interfaces. You can provide an instance of your own implementation.
So, you have two options:
Option 1:
implement java.lang.reflect.ParameterizedType
yourself and pass it to Gson.
private static class ListParameterizedType implements ParameterizedType {
private Type type;
public ListParameterizedType(Type type) {
this.type = type;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[] {type};
}
@Override
public Type getRawType() {
return ArrayList.class;
}
@Override
public Type getOwnerType() {
return null;
}
// implement equals method too! (as per javadoc)
}
Then simply:
Type type = new ListParameterizedType(clazz);
List<T> list = gson.fromJson(json, type);
Note that as per javadoc, equals method should also be implemented.
Option 2: Parse the list manually and then for each element use Gson
public <T> List<T> listEntity(Class<T> clazz)
throws WsIntegracaoException {
try {
// Consuming remote method
String strJson = getService().listEntity(clazz.getName());
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(strJson).getAsJsonArray();
List<T> lst = new ArrayList<T>();
for(final JsonElement json: array){
T entity = GSON.fromJson(json, clazz);
lst.add(entity);
}
return lst;
} catch (Exception e) {
throw new WsIntegracaoException(
"WS method error [listEntity()]", e);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With