使用Gson定制Json序列化

时间:2018-07-30 09:12:24

标签: java json serialization gson

我正在使用一个类层次结构,其中一个类定义了一组实例

public class Base {
    String id;
    String name;
    String type;
} 

public class Group<T extends Base>  extends Base {
    Collection<T> elements;

}

还有许多其他类型都派生自基类,并且可以添加到组中。每种类型都有其自己的属性

Gson默认序列化对于非组对象非常有效,但是对于组对象,我只需要使用基类属性对集合元素进行序列化,而排除所有其他属性。

问题:

  1. 完成这项工作的最佳方法是什么?
  2. 如果Group也是基类,并且我希望为其所有子类自动完成自定义序列化怎么办?

编辑:

@Paul。我认为您的建议不适用于我的情况。 我简化了模型。

这是对该模型的更详尽的描述。

public interface Node {
    BaseObject getAsBaseObject();
}

public class Base {
    String id;
    String name;
    String type;
}

public class BaseObject extends Base implements Node {
    String description;

    @Override
    public BaseObject getAsBaseObject() {
        return this;
    }
}

public class Group<T extends Node>  extends BaseObject {
    Collection<BaseObject> elements;

    void addElement(T element) {
        elements.add(element.getAsBaseObject());
    }
}

Node接口用作复合节点的基础。考虑Foo和Foo的群组...

public interface FooBase extends Node {

}

public class Foo extends BaseObject implements FooBase {
    String prop1;
}

public class FooGroup extends Group<FooBase> implements FooBase{

}

所以可以说我有一个包含一些Foo和Foo组的FooGroup。 我需要序列化的对象看起来像这样:

{
  "id": "",
  "type": "",
  "name": "",
  "description": " ",
  "objects": [
    {
      "type": "",
      "name": "",
      "id": ""
    },
    {
      "type": "",
      "name": "",
      "id": ""
    },
    {
      "type": "",
      "name": "",
      "id": ""
    },
    {
      "type": "",
      "name": "",
      "id": ""
    }
  ]
}

我认为@Expose在这里不起作用,因为description字段也将在对象集合中公开

我能够通过注册自定义JsonSerializer来做到这一点 但这是正确/最简单的方法吗?

如果这是可行的方法,是否有办法只注册一个序列化程序来处理所有Group类派生类?

1 个答案:

答案 0 :(得分:1)

Gson具有一个为此专门制作的@Expose批注。首先,将基类的字段标记为公开:

public class Base {
    @Expose
    String id;
    @Expose
    String name;
    @Expose
    String type;
} 

然后,在创建Gson对象时,使其忽略未公开的字段:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

别忘了还公开elements数组:

public class Group<T extends Base> extends Base {
    @Expose
    Collection<T> elements;
}

串行化现在将按预期工作。为了测试这一点,让我们创建一个扩展Base的小型帮助器类:

public class BaseExtension extends Base {
    private String notExposed;

    public BaseExtension(String notExposed) {
        this.notExposed = notExposed;
    }
}

现在,让我们创建GroupBaseExtension(为清楚起见,请使用Guava):

BaseExtension b1 = new BaseExtension("BaseExt1");
BaseExtension b2 = new BaseExtension("BaseExt2");
BaseExtension b3 = new BaseExtension("BaseExt3");

Group group = new Group<>(Lists.newArrayList(b1, b2, b3));

如果我们对此序列化,则会得到三个没有notExposed属性的元素-实际上,这些元素将完全为空,因为idnametype不会尚有值:

System.out.println(gson.toJson(group));
// Produces { "elements" : [ {}, {}, {} ] }

将值添加到Base类中,以查看更多有用的输出。