[英]Serialize collection as JsonObject instead of JsonArray with GSON
My goal is to serialize a class implementing the Collection interface as JSON object instead of a JSON array. 我的目标是序列化一个将Collection接口实现为JSON对象而不是JSON数组的类。 The following class is a simplyfied example:
以下类是一个简单的示例:
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
...
}
The result of new Gson().toJson(collectionImplementationInstance)
is: new Gson().toJson(collectionImplementationInstance)
是:
["str1","str2",...]
which misses the other field. 错过了另一个领域。 Instead, I would like to get:
相反,我想得到:
{"_wrappedList":["str1","str2"],"_otherField":"asdf"}
Is there a way without manually adding all fields to the JSON? 有没有一种方法可以不手动将所有字段添加到JSON?
Based on this tutorial you can use a JsonSerializer. 根据本教程,您可以使用JsonSerializer。
Note: in the example below I've renamed your class CollectionImpl. 注意:在下面的示例中,我已将您的类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;
}
}
}
Then you can do: 然后,您可以执行以下操作:
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);
As a workaround, one can use Reflection to get an instance of the ReflectiveTypeAdapterFactory
in an own TypeAdapterFactory
: 解决方法是,可以使用
ReflectiveTypeAdapterFactory
在自己的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;
}
}
}
This can be registered with 可以注册到
gsonBuilder.registerTypeAdapterFactory(new CollectionImplementationTypeAdapterFactory());
Does someone know a solution without Reflection? 没有反射,有人知道解决方案吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.