Mou*_*inX 93 java serialization gson
我见过很多使用自定义TypeAdapter的简单示例.最有帮助的是Class TypeAdapter<T>
.但这还没有回答我的问题.
我想自定义对象中单个字段的序列化,让默认的Gson机制处理其余的事情.
出于讨论目的,我们可以将此类定义用作我希望序列化的对象的类.我想让Gson序列化前两个类成员以及基类的所有公开成员,并且我想为下面显示的第三个和最后一个类成员进行自定义序列化.
public class MyClass extends SomeClass {
@Expose private HashMap<String, MyObject1> lists;
@Expose private HashMap<String, MyObject2> sources;
private LinkedHashMap<String, SomeClass> customSerializeThis;
[snip]
}
Run Code Online (Sandbox Code Playgroud)
Jes*_*son 128
这是一个很好的问题,因为它隔离了一些应该很容易但实际上需要大量代码的东西.
首先,编写一个摘要TypeAdapterFactory
,为您提供修改传出数据的钩子.此示例使用Gson 2.2中的新API调用getDelegateAdapter()
,允许您查找Gson默认使用的适配器.如果您只想调整标准行为,则委托适配器非常方便.与完全自定义类型的适配器不同,它们会在您添加和删除字段时自动保持最新状态.
public abstract class CustomizedTypeAdapterFactory<C>
implements TypeAdapterFactory {
private final Class<C> customizedClass;
public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
@SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}
private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<C>() {
@Override public void write(JsonWriter out, C value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
@Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
};
}
/**
* Override this to muck with {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
}
/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected void afterRead(JsonElement deserialized) {
}
}
Run Code Online (Sandbox Code Playgroud)
上面的类使用默认序列化来获取JSON树(由表示JsonElement
),然后调用hook方法beforeWrite()
以允许子类自定义该树.类似地用于反序列化afterRead()
.
接下来,我们将此子类化为特定MyClass
示例.为了说明我将在序列化时向地图添加一个名为"size"的合成属性.对于对称性,我会在反序列化时将其删除.在实践中,这可以是任何定制.
private class MyClassTypeAdapterFactory extends CustomizedTypeAdapterFactory<MyClass> {
private MyClassTypeAdapterFactory() {
super(MyClass.class);
}
@Override protected void beforeWrite(MyClass source, JsonElement toSerialize) {
JsonObject custom = toSerialize.getAsJsonObject().get("custom").getAsJsonObject();
custom.add("size", new JsonPrimitive(custom.entrySet().size()));
}
@Override protected void afterRead(JsonElement deserialized) {
JsonObject custom = deserialized.getAsJsonObject().get("custom").getAsJsonObject();
custom.remove("size");
}
}
Run Code Online (Sandbox Code Playgroud)
最后通过创建Gson
使用新类型适配器的自定义实例将它们放在一起:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new MyClassTypeAdapterFactory())
.create();
Run Code Online (Sandbox Code Playgroud)
Gson的新TypeAdapter和TypeAdapterFactory类型非常强大,但它们也是抽象的,并且可以有效地使用练习.希望你觉得这个例子很有用!
Vic*_*ani 16
还有另一种方法.正如杰西威尔逊所说,这应该很容易.猜猜看,这很容易!
如果实现JsonSerializer
,并JsonDeserializer
为你的类型,你可以处理你想要的部分,并委托GSON的一切,用很少的代码.为了方便起见,我在下面的另一个问题中引用了@ Perception的回答,请参阅答案以获取更多详细信息:
在这种情况下,最好使用a
JsonSerializer
而不是aTypeAdapter
,原因很简单,序列化程序可以访问它们的序列化上下文.Run Code Online (Sandbox Code Playgroud)public class PairSerializer implements JsonSerializer<Pair> { @Override public JsonElement serialize(final Pair value, final Type type, final JsonSerializationContext context) { final JsonObject jsonObj = new JsonObject(); jsonObj.add("first", context.serialize(value.getFirst())); jsonObj.add("second", context.serialize(value.getSecond())); return jsonObj; } }
这个的主要优点(除了避免复杂的解决方法)是您仍然可以利用可能已在主上下文中注册的其他类型适配器和自定义序列化程序.请注意,序列化程序和适配器的注册使用完全相同的代码.
但是,我会承认,如果您经常要修改Java对象中的字段,那么Jesse的方法看起来会更好.这是易用性与灵活性之间的权衡取舍.
我的同事还提到了@JsonAdapter
注释的使用
https://google.github.io/gson/apidocs/com/google/gson/annotations/JsonAdapter.html
例:
private static final class Gadget {
@JsonAdapter(UserJsonAdapter2.class)
final User user;
Gadget(User user) {
this.user = user;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23889 次 |
最近记录: |