Gson如何自定义Calendar序列化/反序列化

直接开干吧,假设有这么一个类:

    @Data
    @AllArgsConstructor
    class BeanSample {
        public Calendar birthday;

        @Override
        public String toString() {
            if (birthday == null) {
                return "birthday:null";
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            return sdf.format(birthday.getTime());
        }
    }

默认情况下,Gson序列化出来的结果很难看:

        Gson gson  = new Gson();
        BeanSample bean = new BeanSample(Calendar.getInstance());
        System.out.println(gson.toJson(bean));

输出:

{"birthday":{"year":2022,"month":3,"dayOfMonth":20,"hourOfDay":21,"minute":18,"second":13}}

以我多年的搬砖经验,加个TypeAdapter应该就可以了:

import com.google.gson.*;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * @author 菩提树下的杨过(yjmyzz.cnblogs.com)
 * @className CalendarTest
 * @description Calendar GSON测试 
 * @date 2022/5/12 22:38
 */
public class CalendarTest {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(GregorianCalendar.class, (JsonSerializer<Calendar>) (src, typeOfSrc, context) -> {
                    //序列化
                    if (src == null) {
                        return JsonNull.INSTANCE;
                    }
                    return new JsonPrimitive(sdf.format(src.getTime()));
                }).registerTypeAdapter(Calendar.class, (JsonDeserializer<Calendar>) (json, typeOfT, context) -> {
                    //反序列化
                    if (json.isJsonNull() || json.getAsString().equals("") || json.getAsString().equalsIgnoreCase("null")) {
                        return null;
                    }

                    if (json.isJsonPrimitive()) {
                        JsonPrimitive asJsonPrimitive = json.getAsJsonPrimitive();
                        //兼容long型时间戳
                        if (asJsonPrimitive.isNumber()) {
                            Calendar instance = Calendar.getInstance();
                            instance.setTimeInMillis(asJsonPrimitive.getAsLong());
                            return instance;
                        }
                        //按字符串解析
                        if (asJsonPrimitive.isString()) {
                            try {
                                Date date = sdf.parse(json.getAsString());
                                Calendar instance = Calendar.getInstance();
                                instance.setTime(date);
                                return instance;
                            } catch (Exception e) {
                            }
                        }
                    }
                    return null;
                }).create();


        BeanSample bean = new BeanSample(Calendar.getInstance());

        //序列化
        String json = gson.toJson(bean);
        System.out.println(json);

        //反序列化
        System.out.println(gson.fromJson(json, BeanSample.class));

        System.out.println("--------");

        //换成时间戳格式
        json = "{\"birthday\":" + bean.birthday.getTimeInMillis() + "}";
        System.out.println(json);
        System.out.println(gson.fromJson(json, BeanSample.class));
    }
}

输出:

{"birthday":"2022-05-12 23:00:12.162"}
2022-05-12 23:00:12.162
--------
{"birthday":1652367612162}
2022-05-12 23:00:12.162

这样看起来好多了,而且json反序列化时,时间戳long型数字也一并做了兼容

 

注:gson的其它小技巧,可参考先前写的文章 去fastjson笔记

posted @ 2022-04-20 22:29  菩提树下的杨过  阅读(334)  评论(0编辑  收藏  举报