Java8 中的日期类序列化问题


自从习惯了使用Java8 中的日期类以后,就已经完全抛弃了java.sqljava.util中的日期处理类,但是Java8中的日期类在序列化与反序列化时不是我们正常看到的标准格式,这里记录一下如何使用Gson进行序列化和反序列化时正常对Java8的日期类进行处理

默认序列化结果

这里写了一个很简单的test,对LocalDateLocalDateTime进行序列化与反序列化

package com.iogogogo;

import com.google.gson.Gson;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * Created by tao.zeng on 2020-01-07.
 */
@Slf4j
public class Java8DateTests {

    @Test
    public void test1() {
        DateMetric dateMetric = new DateMetric();
        dateMetric.setLocalDate(LocalDate.now());
        dateMetric.setLocalDateTime(LocalDateTime.now());

        // serializer
        Gson gson = new Gson();
        String json = gson.toJson(dateMetric);
        log.info("serializer:{}", json);

        // deserializer
        log.info("deserializer:{}", gson.fromJson(json, DateMetric.class));
    }

    @Data
    private class DateMetric implements Serializable {

        private LocalDate localDate;

        private LocalDateTime localDateTime;
    }
}

查看结果,可以看到反序列化的结果是我们自己想要的,但是序列化的结果并不是我们想要的yyyy-MM-dd HH:mm:ss 这种格式,那么这时候就需要用到GsonBuilder来注册registerTypeAdapter

22:09:01.345 [main] INFO com.iogogogo.Java8DateTests - serializer:{"localDate":{"year":2020,"month":1,"day":7},"localDateTime":{"date":{"year":2020,"month":1,"day":7},"time":{"hour":22,"minute":9,"second":1,"nano":271000000}}}

22:09:01.356 [main] INFO com.iogogogo.Java8DateTests - deserializer:Java8DateTests.DateMetric(localDate=2020-01-07, localDateTime=2020-01-07T22:09:01.271)

自定义序列化与反序列化的Adapter

/**
     * 处理LocalDate的序列化与反序列化
     */
final static class LocalDateAdapter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {

  public JsonElement serialize(LocalDate date, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
  }

  @Override
  public LocalDate deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
    String timestamp = element.getAsJsonPrimitive().getAsString();
    return LocalDate.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE);
  }
}

/**
     * 处理LocalDateTime序列化与反序列化
     */
final static class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {

  public JsonElement serialize(LocalDateTime date, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
  }

  @Override
  public LocalDateTime deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
    String timestamp = element.getAsJsonPrimitive().getAsString();
    return LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
  }
}

使用GsonBuilder创建gson对象

@Test
public void test2() {
  DateMetric dateMetric = new DateMetric();
  dateMetric.setLocalDate(LocalDate.now());
  dateMetric.setLocalDateTime(LocalDateTime.now());

  // serializer
  Gson gson = new GsonBuilder()
    .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
    .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
    .create();

  String json = gson.toJson(dateMetric);
  log.info("serializer:{}", json);

  // deserializer
  log.info("deserializer:{}", gson.fromJson(json, DateMetric.class));
}

结果

22:16:15.738 [main] INFO com.iogogogo.Java8DateTests - serializer:{"localDate":"2020-01-07","localDateTime":"2020-01-07T22:16:15.662"}

22:16:15.745 [main] INFO com.iogogogo.Java8DateTests - deserializer:Java8DateTests.DateMetric(localDate=2020-01-07, localDateTime=2020-01-07T22:16:15.662)

输出json进行格式化处理

平时输出的json都是一行文本,如果需要对json的输出结果需要进行格式化处理的话,也可以使用GsonBuildersetPrettyPrinting()方法

@Test
public void test2() {
  DateMetric dateMetric = new DateMetric();
  dateMetric.setLocalDate(LocalDate.now());
  dateMetric.setLocalDateTime(LocalDateTime.now());

  // serializer
  Gson gson = new GsonBuilder()
    .setPrettyPrinting() // 设置输出格式格式化显示
    .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
    .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
    .create();

  String json = gson.toJson(dateMetric);
  log.info("serializer:\n{}", json);

  // deserializer
  log.info("deserializer:{}", gson.fromJson(json, DateMetric.class));
}

输出结果

22:21:03.307 [main] INFO com.iogogogo.Java8DateTests - serializer:
{
  "localDate": "2020-01-07",
  "localDateTime": "2020-01-07T22:21:03.218"
}

22:21:03.313 [main] INFO com.iogogogo.Java8DateTests - deserializer:Java8DateTests.DateMetric(localDate=2020-01-07, localDateTime=2020-01-07T22:21:03.218)

对已有的json进行格式化处理

如果我们的json文本已经存在,那我我们想通过gson进行格式化展示该怎么做呢?

这里做法也很简单,不过JsonObjectJsonArray略有区别,不过都是需要将json读取成JsonObject或者JsonArray对象

JsonObject 格式化

原始JsonObject数据

{"localDate":{"year":2020,"month":1,"day":7},"localDateTime":{"date":{"year":2020,"month":1,"day":7},"time":{"hour":22,"minute":9,"second":1,"nano":271000000}}}
@Test
public void jsonObjectFormatter() {
  JsonObject jsonObject = JsonParser.parseString(JSON_STRING).getAsJsonObject();
  Gson gson = new GsonBuilder().setPrettyPrinting().create();
  System.out.println(gson.toJson(jsonObject));
}

输出结果:

{
  "localDate": {
    "year": 2020,
    "month": 1,
    "day": 7
  },
  "localDateTime": {
    "date": {
      "year": 2020,
      "month": 1,
      "day": 7
    },
    "time": {
      "hour": 22,
      "minute": 9,
      "second": 1,
      "nano": 271000000
    }
  }
}

JsonArray 格式化

原始JsonArray数据

[{"localDate":{"year":2020,"month":1,"day":7},"localDateTime":{"date":{"year":2020,"month":1,"day":7},"time":{"hour":22,"minute":9,"second":1,"nano":271000000}}}]
@Test
public void jsonArrayFormatter() {
  JsonArray jsonArray = JsonParser.parseString(JSON_STRING_ARRAY).getAsJsonArray();
  Gson gson = new GsonBuilder().setPrettyPrinting().create();
  System.out.println(gson.toJson(jsonArray));
}

输出结果:

[
  {
    "localDate": {
      "year": 2020,
      "month": 1,
      "day": 7
    },
    "localDateTime": {
      "date": {
        "year": 2020,
        "month": 1,
        "day": 7
      },
      "time": {
        "hour": 22,
        "minute": 9,
        "second": 1,
        "nano": 271000000
      }
    }
  }
]

总结

本文主要介绍了使用Gson对Java8中的日志进行序列化与反序列化格式的处理,以及使用gson对json进行格式化的输出。

参考地址:Serialize Java 8 LocalDate as yyyy-mm-dd with Gson

完整代码:Java8DateTests


文章作者: 阿牛
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿牛 !
评论
  目录