将 JSON 反序列化为瞬态字段
Deserialize JSON into transient field
我有一个包含这些字段的 class:
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,只在序列化期间而不是在反序列化期间有一些字段瞬变?
你有两个选择。
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 && !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));
}
}
产生以下结果:
localhost:1234
{"name":"game1","points":11,"size":10}
我有一个包含这些字段的 class:
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,只在序列化期间而不是在反序列化期间有一些字段瞬变?
你有两个选择。
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 && !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));
}
}
产生以下结果:
localhost:1234
{"name":"game1","points":11,"size":10}