我有一个与这些领域的课程:

private transient List<Peer> peers;
private final String name;
private final int points;
private final int size;


我想使用Gson反序列化此JSON字符串请求:

{
    "name": "game1",
    "points": "11",
    "size": "10",
    "peers": [
        {
            "address": "localhost",
            "port": 1234,
            "fullAddress": "localhost:1234"
        }
    ]
}


我的问题是Peer对象不会反序列化到peers列表中,除非我不将字段声明为瞬态。

使用Gson,是否有办法仅在序列化期间而不在反序列化期间具有某些场瞬变?

最佳答案

您有两个选择。

excludeFieldsWithoutExposeAnnotation()

Gson提供了精确目的的@Expose。这里唯一的警告是您必须注释每个字段:

private static final Gson gson = new GsonBuilder()
        .excludeFieldsWithoutExposeAnnotation()
        .create();


@Expose(serialize = false) final List<Peer> peers;
@Expose final String name;
@Expose final int points;
@Expose final int size;


addSerializationExclusionStrategy(...)

说,您可以轻松地引入如下内容:

@Target(FIELD)
@Retention(RUNTIME)
@interface ReadOnly {
}


现在,一旦声明了该策略,就可以将策略注册到Gson实例:

private static final Gson gson = new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(final FieldAttributes f) {
                return f.getAnnotation(ReadOnly.class) != null;
            }

            @Override
            public boolean shouldSkipClass(final Class<?> clazz) {
                return false;
            }
        })
        .create();


@ReadOnly final List<Peer> peers;
final String name;
final int points;
final int size;


您只需在策略中使用@Expose之类的方法即可轻松地将f.getAnnotation(Expose.class) != null && !f.getAnnotation(Expose.class).serialize()用于选项#2,但我发现@ReadOnly更为方便。

对于这两个选项,以下代码

public static void main(final String... args)
        throws IOException {
    try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43893428.class, "foo.json") ) {
        final Foo foo = gson.fromJson(jsonReader, Foo.class);
        for ( final Peer peer : foo.peers ) {
            System.out.println(peer.fullAddress);
        }
        System.out.println(gson.toJson(foo));
    }
}


产生以下结果:


  本地主机:1234
  {“ name”:“ game1”,“ points”:11,“ size”:10}

10-07 13:21