【问题标题】:Deserialize JSON into transient field将 JSON 反序列化为瞬态字段
【发布时间】:2017-05-10 13:07:05
【问题描述】:

我有一个包含这些字段的课程:

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 列表中,除非我没有将该字段声明为 transient

Gson 有没有办法只在序列化期间而不是在反序列化期间有一些字段瞬态?

【问题讨论】:

  • 这就是java中transient关键字的意义所在。这意味着您不能反序列化该属性。你应该看看this
  • 我知道。没有什么可以让我只反序列化某些字段而不序列化它?
  • @gioaudino 你用 Gson 尝试过 addDeserializationExclusionStrategy() 吗?

标签: java json serialization gson transient


【解决方案1】:

你有两个选择。

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 用于选项#2,只需在策略中使用f.getAnnotation(Expose.class) != null &amp;&amp; !f.getAnnotation(Expose.class).serialize() 之类的东西处理它,但我发现@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}

【讨论】:

  • 我选择了@Expose 选项,使用起来非常快。谢谢
  • addSerializationExclusionStrategy 对我来说就像一个魅力!谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 2015-10-18
  • 2022-12-11
相关资源
最近更新 更多