除了默认的序列化和反序列化行为,gson还允许自定义某些类的序列化和反序列化行为。自定义行为一般用于需要使json对象具有和原来类不同的表示形式,或者默认行为会报错的情况。主要分为三个类
Json Serializers: 自定义某种对象类型的序列化行为
Json Deserializers: 自定义某种对象类型的反序列化行为
Instance Creators: 自定义某种对象的创建行为
此时我们需要配置gsonbuilder,然后用gsonbuilder来创建gson对象,builder模式大家应该很熟悉了
代码如下
GsonBuilder gsonBuilder= new GsonBuilder();
gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerTypeAdapter(MyType.class, new MyDeserializer());
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
Gson gson=gsonBuilder.create();
为某类型注册了自定义的序列化和反序列化行为之后,在转换的过程中一旦遇到该类型的对象,就会调用你注册的行为来序列化。
这些的类的实现也很容易。
//自定义序列化,需要实现JsonSerializer接口
private class DateTimeSerializer implements JsonSerializer<DateTime> {
public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toString());
}
}
//自定义序列化,需要实现DateTimeDeserializer 接口
private class DateTimeDeserializer implements JsonDeserializer<DateTime> {
public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return new DateTime(json.getAsJsonPrimitive().getAsString());
}
}
//自定义对象创建,需要实现InstanceCreator
private class MoneyInstanceCreator implements InstanceCreator<Money> {
public Money createInstance(Type type) {
return new Money("1000000", CurrencyCode.USD);
}
}
在我个人使用gson的过程中,我发现有些时候是不得不用自定义序列化和反序列化的,因为在使用默认的行为的情况下,对一些复杂对象经常出错,具体原因我也不知道为什么,很多时候都是出现了死循环,可能java一些类中本身就存在双向引用吧,此外还有一些其他的异常,主要原因都是java一些类本身的继承结构太深了。
我们以序列化Image为例(该类直接序列化会报错)
这个代码是我实际项目中使用的,将javafx的image对象序列化(当然对于图像对象,最后还要使用压缩流来减少体积)
public class GsonImage implements JsonSerializer<Image>,JsonDeserializer<Image> {
@Override
public Image deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
Gson gson=new Gson();
byte[] bs=gson.fromJson(json.getAsString(), byte[].class);
BufferedImage image = null;
try {
//从字节数组创建图片
image = ImageIO.read(new ByteArrayInputStream(bs));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Image image2=SwingFXUtils.toFXImage(image, null);
return image2;
}
@Override
public JsonElement serialize(Image image, Type typeOfSrc, JsonSerializationContext context) {
Gson gson=new Gson();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
BufferedImage bufferedImage=SwingFXUtils.fromFXImage(image, null);
try {
ImageIO.write(bufferedImage, "PNG", stream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] imgBytes=stream.toByteArray();
//实际上序列化的是字节数组
String string=gson.toJson(imgBytes);
return new JsonPrimitive(string);
}
}
除了三种自定义行为之外,gsonbuilder还提供了一些配置
setPrettyPrinting() //设置输出格式为可读性优先(默认是体积小优先)
serializeNulls() //设置输出null(默认null会被忽略)
excludeFieldsWithModifiers()//设置不被包括在序列化中的修饰符(默认为static //transient,但是你可以覆盖设置)
关于gson就介绍到这里
可以访问gson的github帮助页面来获取更多信息
https://github.com/google/gson/blob/master/UserGuide.md