Gson系列5 --- 总结篇 -- TypeAdapter JsonSerializer 与 JsonDeserializer @JsonAdapter

# 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);
    }
}



你可能感兴趣的:(Gson系列)