2017-10-11 202 views
0

我的目标是将实现Collection接口的类序列化为JSON对象而不是JSON数组。以下类是simplyfied例如:序列化JSONObject集合而不是JSONArray与GSON

public class CollectionImplementation implements Collection<String> { 
    private final List<String> _wrappedList = new LinkedList<>(); 
    private String _otherField = "asdf"; 

    @Override 
    public boolean add(String e) { 
    return _wrappedList.add(e); 
    } 

    @Override 
    ... 
} 

new Gson().toJson(collectionImplementationInstance)结果是:

["str1","str2",...] 

其射门其他字段。相反,我想得到:

​​

有没有一种方法没有手动添加所有字段到JSON?

+0

我发现CollectionTypeAdapterFactory负责创建一个创建JSON数组的类型适配器,而ReflectiveTypeAdapterFactory将创建导致我的目标的类型适配器。我知道委托给其他类型的适配器,但我如何从ReflectiveTypeAdapterFactory获取类型适配器的有效实例? – efzwo

回答

0

根据this tutorial您可以使用JsonSerializer。

注意:在下面的示例中,我已将您的类CollectionImpl重命名。

public class CollectionImpl implements Collection<String> { 

    private final List<String> _wrappedList = new LinkedList<>(); 
    private String _otherField = "asdf"; 

    // ... 

    // Note: I've created the class as subclass of CollectionImpl in order to access the 
    // private fields without implementing a getter (as you maybe want to keep 
    // your fields completely private) 
    public static class CollectionImplJsonSerializer implements JsonSerializer<CollectionImpl> { 
     @Override 
     public JsonElement serialize(CollectionImpl src, Type typeOfSrc, JsonSerializationContext context) { 
      JsonObject jsonColl = new JsonObject(); 
      JsonArray array = new JsonArray(); 

      for (String s: src._wrappedList) { 
       array.add(s); 
      } 

      jsonColl.add("_wrappedList", array); 
      jsonColl.addProperty("_otherField", src._otherField); 


      return jsonColl; 
     } 
    } 
} 

然后,你可以这样做:

CollectionImpl ci = new CollectionImpl(); 

GsonBuilder builder = new GsonBuilder(); 
CollectionImpl.CollectionImplJsonSerializer serializer = new CollectionImpl.CollectionImplJsonSerializer(); 
builder.registerTypeAdapter(CollectionImpl.class, serializer); 
Gson gson = builder.create(); 

String json = gson.toJson(ci); 
+0

正如我的问题所写,我正在寻找一个解决方案,而无需手动添加所有字段/属性。 – efzwo

+0

对不起,我错过了这一行。不要以为你可以不使用串行器/解串器。 Idk你试图达到什么目标,但另一种选择可能是你的课没有实现'Collection <>' – Eselfar

0

作为一种变通方法,可以使用反射在自己的TypeAdapterFactory得到ReflectiveTypeAdapterFactory的一个实例:

public class CollectionImplementationTypeAdapterFactory implements TypeAdapterFactory { 
    @Override 
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
    if (!type.getRawType().equals(CollectionImplementation.class)) { 
     return null; 
    } 
    try { 
     Field factoriesField = Gson.class.getDeclaredField("factories"); 
     factoriesField.setAccessible(true); 
     @SuppressWarnings("unchecked") 
     List<TypeAdapterFactory> factories = (List<TypeAdapterFactory>) factoriesField.get(gson); 
     TypeAdapterFactory typeAdapterFactory = factories.stream().filter(f -> f instanceof ReflectiveTypeAdapterFactory).findAny().get(); 
     return typeAdapterFactory.create(gson, type); 
    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) { 
     return null; 
    } 
    } 
} 

这可以被注册与

gsonBuilder.registerTypeAdapterFactory(new CollectionImplementationTypeAdapterFactory()); 

有人知道没有反射的解决方案吗?