序列化JSONObject集合而不是JSONArray与GSON
问题描述:
我的目标是将实现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?
答
根据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);
答
作为一种变通方法,可以使用反射在自己的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());
有人知道没有反射的解决方案吗?
我发现CollectionTypeAdapterFactory负责创建一个创建JSON数组的类型适配器,而ReflectiveTypeAdapterFactory将创建导致我的目标的类型适配器。我知道委托给其他类型的适配器,但我如何从ReflectiveTypeAdapterFactory获取类型适配器的有效实例? – efzwo