2017-10-11 208 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()); 

有人知道沒有反射的解決方案嗎?