1. 程式人生 > 其它 >Gson如何自定義Calendar序列化/反序列化 去fastjson筆記

Gson如何自定義Calendar序列化/反序列化 去fastjson筆記

直接開幹吧,假設有這麼一個類:

    @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應該就可以了吧:

        Gson gson = new GsonBuilder().registerTypeAdapter(Calendar.class, new TypeAdapter<Calendar>() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

            @Override
            public void write(JsonWriter out, Calendar value) throws IOException {
                if (value == null) {
                    out.nullValue();
                } else {
                    out.value(sdf.format(value.getTime()));
                }
            }

            @Override
            public Calendar read(JsonReader in) throws IOException {
                //這是從json字串反序列化的,先不管
                return null;
            }
        }).create();
        
        BeanSample bean = new BeanSample(Calendar.getInstance());
        System.out.println(gson.toJson(bean));

執行一下,居然沒生效,還是剛才的格式!於是,下個斷點:

發現birthday最終例項化後,型別是 GregorianCalendar(即:抽象類Calendar的子類),然後把剛才的程式碼略改了下:

Gson gson = new GsonBuilder().registerTypeAdapter(GregorianCalendar.class, new TypeAdapter<GregorianCalendar>() {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    @Override
    public void write(JsonWriter out, GregorianCalendar value) throws IOException {
        if (value == null) {
            out.nullValue();
        } else {
            out.value(sdf.format(value.getTime()));
        }
    }

    @Override
    public GregorianCalendar read(JsonReader in) throws IOException {
        JsonToken token = in.peek();
        switch (token) {
            case NUMBER:
                Date d = new Date(in.nextLong());
                GregorianCalendar c = new GregorianCalendar();
                c.setTime(d);
                return c;
            case STRING:
                String s = in.nextString();
                try {
                    Date parse = sdf.parse(s);
                    GregorianCalendar instance = new GregorianCalendar();
                    instance.setTime(parse);
                    return instance;
                } catch (ParseException e) {
                    e.printStackTrace();
                    return null;
                }
            case NULL:
            default:
                return null;
        }
    }
}).create();


BeanSample bean = new BeanSample(new GregorianCalendar());

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

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

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

//換成時間戳格式
json = "{\"birthday\":" + System.currentTimeMillis() + "}";
System.out.println(json);
System.out.println(gson.fromJson(json, BeanSample.class));

輸出:

{"birthday":"2022-04-20 22:27:08.864"}
2022-04-20 22:27:08.864
--------
{"birthday":1650464828881}
2022-04-20 22:27:08.881

這樣看起來好多了,而且json反序列化時,時間戳long型數字也一併做了相容

 

注:gson的其它小技巧,可參考先前寫的文章 去fastjson筆記