使用GSON将集合序列化为JsonObject而不是JsonArray

时间:2017-10-11 10:41:43

标签: java arrays json serialization gson

我的目标是将实现Collection接口的类序列化为JSON对象而不是JSON数组。以下类是一个简单的例子:

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",...]

错过了另一个领域。相反,我想得到:

{"_wrappedList":["str1","str2"],"_otherField":"asdf"}

有没有办法没有手动将所有字段添加到JSON?

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

作为一种解决方法,可以使用Reflection在自己的ReflectiveTypeAdapterFactory中获取TypeAdapterFactory的实例:

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());

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