# TypeAdapter JsonSerializer 与 JsonDeserializer @JsonAdapter 类的序列化与反序列化 @SEE @JsonAdapter篇 和 序列化null值 方式1: JsonSerializer 与 JsonDeserializer 可以 自动的与 @JsonAdapter 使用 方式2: 也可以手动注册到 registerTypeAdapter中去。 方式1的案例 见 date时间类型的转换 方式2的案例 见自定义类型的转换
参考链接 1
关于日期形式的序列化
package sun.rain.amazing.gson.serializer; import com.google.gson.*; import java.lang.reflect.Type; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * @author sunRainAmazing */ public class DateSerializer implements JsonSerializer,JsonDeserializer { private DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); /** * * @param src 所需要序列化的值 * @param typeOfSrc 序列化的类型 * @param context 序列化的操作 * @return */ @Override public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(df.format(src)); } @Override public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { /** * 若读取到的字符串 为 "" 或者 "null" * 则返回 null */ String res = json.getAsString(); if (res.length()<5){ return null; } try { return df.parse(res); } catch (ParseException e) { throw new JsonParseException("日期格式不正确 应该为 yyyy-MM-dd"); } } }
package sun.rain.amazing.gson.serializer; import com.google.gson.*; import java.lang.reflect.Type; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * @author sunRainAmazing */ public class DateTimeSerializer implements JsonSerializer,JsonDeserializer { private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * * @param src 所需要序列化的值 * @param typeOfSrc 序列化的类型 * @param context 序列化的操作 * @return */ @Override public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { return context.serialize(df.format(src)); } @Override public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { /** * 若读取到的字符串 为 "" 或者 "null" * 则返回 null */ String res = json.getAsString(); if (res.length()<5){ return null; } try { return df.parse(res); } catch (ParseException e) { throw new JsonParseException("日期格式不正确 应该为 yyyy-MM-dd"); } } }
package sun.rain.amazing.gson.serializer; import com.google.gson.*; import java.lang.reflect.Type; import java.time.LocalDate; import java.time.format.DateTimeFormatter; /** * 对于 非 null 值的 LocalDate的序列化 * * @author sunRainAmazing */ public class LocalDateSerializer implements JsonSerializer, JsonDeserializer { private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) { return null == src ? null : new JsonPrimitive(formatter.format(src)); } @Override public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String res = json.getAsString(); if(null == json || res.length()<1){ return null; } return LocalDate.parse(json.getAsString(), formatter); } }
package sun.rain.amazing.gson.serializer; import com.google.gson.*; import java.lang.reflect.Type; import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; /** * 对于 非 null 值的 ZonedDateTime 的序列化 * * @author sunRainAmazing */ public class ZonedDateTimeSerializer implements JsonSerializer, JsonDeserializer { private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public JsonElement serialize(ZonedDateTime src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(formatter.format(src)); } @Override public ZonedDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String res = json.getAsString(); if(res == null || res.length() <1){ return null; } return null == json ? null : ZonedDateTime.parse(json.getAsString(), formatter.withZone(ZoneId.of("Asia/Shanghai"))); } }
基本类
package sun.rain.amazing.gson.serializer; import com.google.gson.annotations.JsonAdapter; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.Date; /** * @author sunRainAmazing */ @Data @NoArgsConstructor @AllArgsConstructor public class GsonSerializer { private String name; @JsonAdapter(DateSerializer.class) private Date birthday; @JsonAdapter(DateTimeSerializer.class) private Date createTime; @JsonAdapter(LocalDateSerializer.class) private LocalDate upDay; @JsonAdapter(ZonedDateTimeSerializer.class) private ZonedDateTime regTime; public GsonSerializer(String name) { this.name = name; } }
测试类
package sun.rain.amazing.gson.serialize; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.junit.Test; import sun.rain.amazing.gson.serializer.GsonSerializer; import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.Date; /** * @author sunRainAmazing */ public class GsonSerializerTest { private Gson gson = new Gson(); /** * {"name":"tom","birthday":"2018-07-09", * "createTime":"2018-07-09 14:04:12", * "upDay":"2018-07-09","regTime":"2018-07-09 14:04:12"} * * GsonSerializer(name=tom, birthday=Mon Jul 09 00:00:00 CST 2018, * createTime=Mon Jul 09 14:04:12 CST 2018, upDay=2018-07-09, * regTime=2018-07-09T14:04:12+08:00[Asia/Shanghai]) */ @Test public void testGsonSerializer1(){ String json = gson.toJson(new GsonSerializer("tom",new Date(),new Date() ,LocalDate.now(), ZonedDateTime.now())); System.out.println(json); GsonSerializer g = gson.fromJson(json,GsonSerializer.class); System.out.println(g); } }
关于Enum类的序列化
public interface GsonSerializer{ /** * 序列化接口 * @return */ String serialize(); }
package sun.rain.amazing.gson.serializer.enums; /** * 确保只接收枚举并且GsonEnum只被枚举类所实现,可以添加泛型参数的边界,如下: * @author sunRainAmazing */ public interface GsonDeserializer<T extends Enum<T>> { /** * 反序列化接口 * 反序列化时的参数 --- 必须是String类型 * @param value * @return */ T deserialize(String value); }
/** * @author sunRainAmazing */ public interface GsonSerialization<T extends Enum<T>> extends GsonSerializer,GsonDeserializer<T> { }
自定义枚举的TypeAdapter
package sun.rain.amazing.gson.serializer.enums; import com.google.gson.*; import java.lang.reflect.Type; /** * @author sunRainAmazing */ public class GsonSerializationTypeAdapter<T extends Enum<T>> implements JsonSerializer<T>,JsonDeserializer<T> { private final GsonSerialization<T> gsonSerialization; public GsonSerializationTypeAdapter(GsonSerialization<T> gsonSerialization) { this.gsonSerialization = gsonSerialization; } /** * 反序列化操作 * @param json * @param typeOfT * @param context * @return * @throws JsonParseException */ @Override public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json != null ) { return gsonSerialization.deserialize(json.getAsString()); } return null; } /** * 序列化操作 * @param src * @param typeOfSrc * @param context * @return */ @Override public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { if (src != null && src instanceof GsonSerialization) { /** * 这里 只能接受 String */ return new JsonPrimitive(((GsonSerialization)src).serialize()); } return null; } }
枚举类要实现上面的枚举序列化接口
package sun.rain.amazing.gson.serializer.enums; /** * @author sunRainAmazing */ public enum GsonType implements GsonSerialization{ A,B,C,D,E ; @Override public GsonType deserialize(String value) { GsonType[] vs = values(); for (int i = 0; i < vs.length ; i++) { if(vs[i].name().equalsIgnoreCase(value)){ return vs[i]; } } return null; } @Override public String serialize() { return this.toString(); } }
package sun.rain.amazing.gson.serializer.enums; import lombok.Getter; /** * @author sunRainAmazing */ public enum GsonWorkStatusInfo implements GsonSerialization{ COMPLETE(0,"完成"), // 完成 FINISH(10,"结束"), // 结束 SUCCESS(20,"成功"),// 成功 WARNING(30,"警告"),//警告 INFO(40,"通知"),//通知 ERROR(50,"错误"),//错误 FAILURE(60,"失败"),//失败 OK(70,"操作完成"),//操作完成 NG(80,"操作失败"),//操作失败 ; @Getter private Integer flag; @Getter private String value; GsonWorkStatusInfo(Integer flag, String value) { this.flag = flag; this.value = value; } /** * 根据名称 获取对应的 对象 * @param value * @return */ public static GsonWorkStatusInfo getByValue(String value){ GsonWorkStatusInfo[] values = GsonWorkStatusInfo.values(); for (int i = 0; i length ; i++) { if(values[i].getValue().equalsIgnoreCase(value)){ return values[i]; } } return null; } /** * 根据标志值 或去到 对应的实例 * @param flag * @return */ public static GsonWorkStatusInfo getByFlag(String flag){ GsonWorkStatusInfo[] values = GsonWorkStatusInfo.values(); for (int i = 0; i length ; i++) { if(values[i].getFlag().toString().equalsIgnoreCase(flag)){ return values[i]; } } return null; } @Override public GsonWorkStatusInfo deserialize(String flag) { return getByFlag(flag); } @Override public String serialize() { return this.getFlag().toString() .concat("-") .concat(this.getValue()); } }
相关实体类
package sun.rain.amazing.gson.serializer.enums; import com.google.gson.annotations.JsonAdapter; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import sun.rain.amazing.gson.serializer.DateSerializer; import java.util.Date; /** * @author sunRainAmazing */ @Data @AllArgsConstructor @NoArgsConstructor public class GsonEnumEntity { private int id; private String name; private GsonType type; private GsonWorkStatusInfo statusInfo; @JsonAdapter(DateSerializer.class) private Date birthday; }
相关测试类
package sun.rain.amazing.gson.serialize; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.junit.Test; import sun.rain.amazing.gson.serializer.enums.GsonEnumEntity; import sun.rain.amazing.gson.serializer.enums.GsonSerializationTypeAdapter; import sun.rain.amazing.gson.serializer.enums.GsonType; import sun.rain.amazing.gson.serializer.enums.GsonWorkStatusInfo; import java.util.Date; /** * @author sunRainAmazing */ public class GsonEnumTest { Gson gson = new Gson(); /** * {"id":1001,"name":"tom","type":"C", * "statusInfo":"COMPLETE","birthday":"2018-07-09"} * GsonEnumEntity(id=1001, name=tom, type=C, statusInfo=COMPLETE, * birthday=Mon Jul 09 00:00:00 CST 2018) * * {"id":1001,"name":"tom","type":"C","statusInfo":"0-完成","birthday":"2018-07-09"} * GsonEnumEntity(id=1001, name=tom, type=C, * statusInfo=COMPLETE, birthday=Mon Jul 09 00:00:00 CST 2018) */ @Test public void test(){ GsonEnumEntity g = new GsonEnumEntity(1001,"tom", GsonType.C, GsonWorkStatusInfo.COMPLETE, new Date()); String json = gson.toJson(g); System.out.println(json); g = gson.fromJson(json,GsonEnumEntity.class); System.out.println(g); // 使用 JsonBuilder 进行注册 registerTypeAdapter gson = new GsonBuilder() .registerTypeAdapter(GsonType.class, new GsonSerializationTypeAdapter<>(GsonType.C)) .registerTypeAdapter(GsonWorkStatusInfo.class, new GsonSerializationTypeAdapter<>(GsonWorkStatusInfo.NG)) .create(); json = gson.toJson(g); System.out.println(json); // 自定义 json 格式 json = "{\"id\":1001,\"name\":\"tom\",\"type\":\"C\"," + "\"statusInfo\":\"0\",\"birthday\":\"2018-07-09\"}"; g = gson.fromJson(json,GsonEnumEntity.class); System.out.println(g); } }