如何使用Gson序列化Optional 类?

我有一个具有以下属性的对象。

private final String messageBundle; private final List messageParams; private final String actionBundle; private final Map data; private final Optional<Pair> ttl; private final Optional badgeNumber; private final Optional collapseKey; 

该对象位于库中,我宁愿不仅仅为了序列化目的而修改它,并且希望避免创建另一个DTO的成本。

如何序列化/反序列化可选属性? 可选没有默认构造函数(apache commons Pair),但我不能使用InstanceCreator,并且不太了解如何创建一个简单地将序列化委托给底层Optional内容的TypeAdapter。

Ilya的解决方案忽略了类型参数,因此它在一般情况下无法真正起作用。 我的解决方案相当复杂,因为需要区分nullOptional.absent() – 否则你可以将封装作为列表去掉。

 public class GsonOptionalDeserializer implements JsonSerializer>, JsonDeserializer> { @Override public Optional deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { final JsonArray asJsonArray = json.getAsJsonArray(); final JsonElement jsonElement = asJsonArray.get(0); final T value = context.deserialize(jsonElement, ((ParameterizedType) typeOfT).getActualTypeArguments()[0]); return Optional.fromNullable(value); } @Override public JsonElement serialize(Optional src, Type typeOfSrc, JsonSerializationContext context) { final JsonElement element = context.serialize(src.orNull()); final JsonArray result = new JsonArray(); result.add(element); return result; } } 

经过几个小时的gooling和编码 – 有我的版本:

 public class OptionalTypeAdapter extends TypeAdapter> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @Override public  TypeAdapter create(Gson gson, TypeToken type) { Class rawType = (Class) type.getRawType(); if (rawType != Optional.class) { return null; } final ParameterizedType parameterizedType = (ParameterizedType) type.getType(); final Type actualType = parameterizedType.getActualTypeArguments()[0]; final TypeAdapter adapter = gson.getAdapter(TypeToken.get(actualType)); return new OptionalTypeAdapter(adapter); } }; private final TypeAdapter adapter; public OptionalTypeAdapter(TypeAdapter adapter) { this.adapter = adapter; } @Override public void write(JsonWriter out, Optional value) throws IOException { if(value.isPresent()){ adapter.write(out, value.get()); } else { out.nullValue(); } } @Override public Optional read(JsonReader in) throws IOException { final JsonToken peek = in.peek(); if(peek != JsonToken.NULL){ return Optional.ofNullable(adapter.read(in)); } return Optional.empty(); } } 

您可以像GsonBuilder一样简单地注册它:

 instance.registerTypeAdapterFactory(OptionalTypeAdapter.FACTORY) 

请注意,如果json中没有字段,Gson不会为您的类字段设置值。 因此,您需要在实体中设置默认值Optional.empty()

你可能想尝试这个gson模块 ,它可以处理java8可选类型序列化/反序列化(以及als java8新日期类型)。

正如maaartinus解决方案的补充,没有封装列表的版本,其中Optional.absent被简单地序列化为null

 public class GsonOptionalDeserializer implements JsonSerializer>, JsonDeserializer> { @Override public Optional deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { final T value = context.deserialize(json, ((ParameterizedType) typeOfT).getActualTypeArguments()[0]); return Optional.fromNullable(value); } @Override public JsonElement serialize(Optional src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(src.orNull()); } 

}