2013-07-22 2 views
2

Я хочу, чтобы все были дезериализованы в немодифицируемые коллекции.Deserialize Список в немодифицируемую коллекцию с gson

Вот мой класс, я десериализация:

public class MyClass 
{ 
    public final mylist = Collections.unmodifiablelist(new ArrayList()); 
} 

Как десериализации:

MyClass inst = (new Gson()).fromJson("{mylist:[\"firstString\"]}", MyClass.class); 

Я не хочу, чтобы создать зарегистрировать адаптер типа для всех 100 классов которые используют List, так есть способ глобально переопределить десериализуемый List для этого экземпляра Gson?

+0

Где находится тип поля 'mylist'? – PomPom

ответ

0

Я бы с переходником фабрики тоже, но короче код:

class MyAdapter implements TypeAdapterFactory { 

    @Override 
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> tokenType) { 
    final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, tokenType); 

    return new TypeAdapter<T>() { 
     @Override 
     public void write(JsonWriter out, T value) throws IOException { 
     delegate.write(out, value); 
     } 

     @Override 
     public T read(JsonReader arg0) throws IOException { 
     T t = delegate.read(arg0); 
     if (List.class.isAssignableFrom(tokenType.getRawType())) { 
      List<?> list = (List<?>) t; 

      return (T) Collections.unmodifiableList(list); 
     } 

     return t; 
     } 
    }; 
    } 
} 

Затем, как обычно, r egister it:

1

Почему вы не просто следуете стандартам JavaBean и просто возвращаете немодифицируемые списки?

public class MyClass { 
    private List<String> myList = new ArrayList<String>(); 

    public void setMyList(List<String> list) { 
     this.myList = list; 
    } 

    public Collection<String> getMyList() { 
     return Collections.unmodifiablelist(this.myList); 
    } 
} 
+0

... потому что экземпляр 'myList' также используется внутри ... Я бы предпочел по соображениям здравомыслия, чтобы он не поддавался изменению. – Cheetah

+0

imho, если вы не можете доверять своему собственному классу, чтобы не вносить изменений, у вас больше проблем – epoch

+0

... это не дело доверия ... больше о рассуждении, если кто-то придет, чтобы отредактировать мой класс позже. .. если он не поддается изменению, это заставит разработчика остановиться и подумать, почему это было сделано ... – Cheetah

0

С новой версией Gson вы можете создавать собственные TypeAdapterFactory для List свойств. Я реализовал простой UnmodifiableListTypeAdapter, но я не уверен, что все в порядке. Пожалуйста, прочитайте в документации, как правильно ее реализовать.

class ListTypeAdapterFactory implements TypeAdapterFactory { 

    @SuppressWarnings({ "rawtypes", "unchecked" }) 
    @Override 
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { 
     Type type = typeToken.getType(); 
     if (typeToken.getRawType() != List.class || !(type instanceof ParameterizedType)) { 
      return null; 
     } 

     Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; 
     TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType)); 

     return new UnmodifiableListTypeAdapter(elementAdapter); 
    } 
} 

class UnmodifiableListTypeAdapter<E> extends TypeAdapter<List<E>> { 

    private TypeAdapter<E> elementAdapter; 

    public UnmodifiableListTypeAdapter(TypeAdapter<E> elementAdapter) { 
     this.elementAdapter = elementAdapter; 
    } 

    @Override 
    public List<E> read(JsonReader reader) throws IOException { 
     if (reader.peek() == JsonToken.NULL) { 
      reader.nextNull(); 
      return null; 
     } 

     List<E> list = new ArrayList<E>(); 
     reader.beginArray(); 
     while (reader.hasNext()) { 
      E element = elementAdapter.read(reader); 
      list.add(element); 
     } 
     reader.endArray(); 

     return Collections.unmodifiableList(list); 
    } 

    @Override 
    public void write(JsonWriter writer, List<E> list) throws IOException { 
     if (list == null) { 
      writer.nullValue(); 
      return; 
     } 

     writer.beginArray(); 
     for (E item : list) { 
      elementAdapter.write(writer, item); 
     } 
     writer.endArray(); 
    } 
} 

Пример использования МОГ выглядит следующим образом:

public class GsonProgram { 

    public static void main(String[] args) throws Exception { 
     GsonBuilder gsonBuilder = new GsonBuilder(); 
     gsonBuilder.registerTypeAdapterFactory(new ListTypeAdapterFactory()); 
     Gson gson = gsonBuilder.create(); 

     System.out.println(gson.fromJson("{strings:[\"firstString\"],integers:[23,34,56]}", 
       Entity.class)); 
    } 
} 

class Entity { 

    private List<String> strings; 
    private List<Integer> integers; 

    public List<String> getStrings() { 
     return strings; 
    } 

    public void setStrings(List<String> strings) { 
     this.strings = strings; 
    } 

    public List<Integer> getIntegers() { 
     return integers; 
    } 

    public void setIntegers(List<Integer> integers) { 
     this.integers = integers; 
    } 

    @Override 
    public String toString() { 
     return "Entity [strings=" + strings + ", integers=" + integers + "]"; 
    } 
} 

Над программа печатает:

Entity [strings=[firstString], integers=[23, 34, 56]]