Destroy Shared List in Gson

I want to write a generic function that deserializes a generic List with Gson type, 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 does not work, I get a strange structure, but not a list of my type

When i use:

 List<concreteType> something = gson.fromJson(data, new TypeToken<List<T>>(){}.getType()); 

i works, i get List<concreteType> !!

But I need a general function, how can I fix it?

Relationship rubiktubik

+4
source share
2 answers

There is no way to do this without passing the actual type of T (as Class<T> ) to your method.

But if you pass it explicitly, you can create a TypeToken for List<T> as follows:

 private <T> List<T> GetListFromFile(String filename, Class<T> elementType) { ... TypeToken<ArrayList<T>> token = new TypeToken<ArrayList<T>>() {}; List<T> something = gson.fromJson(data, token.getType()); ... } 

See also:

+3
source

The TypeToken usage approach will not work.

 new TypeToken<ArrayList<T>>() 

impossible due to how generics (type erasure) and reflection work. The whole TypeToken trick works because Class#getGenericSuperclass() does the following

Returns a type representing the direct superclass of the object (class, interface, primitive type, or void) represented by this class.

If the superclass is a parameterized type, the returned Type object must accurately reflect the actual type parameters used in the source code.

In other words, if he sees ArrayList<T> , then ParameterizedType returned, and you cannot retrieve the compile-time value that a variable of type T would have.

Type and ParameterizedType are both interfaces. You can provide an instance of your own implementation.

So, you have two options:

Option 1: Add 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 just:

 Type type = new ListParameterizedType(clazz); List<T> list = gson.fromJson(json, type); 

Note that according to javadoc , the equals method must also be implemented.

Option 2: Parse the list manually, then use Gson for each item

 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); } } 
+7
source

Source: https://habr.com/ru/post/1497862/


All Articles