ikki@github.io:~$

序列化反序列化常用设置

序列化和反序化的实用配置

Jackson-时间

序列化

  • Date 序列化为时间戳
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
    
spring.jackson.serialization.write-dates-as-timestamps=true
  • JDK8
objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false ); 
spring.jackson.serialization.write-date-timestamps-as-nanoseconds=false
  • java.time.Instantjava.time.ZonedDateTime 类型会序列化为 毫秒级时间戳

反序列化

  • 毫秒级时间戳会顺利反序列化为java.util.Date
  • JDK8
//不把时间戳当成nanoseconds, 否则会把毫秒当成秒读
objectMapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,false);
spring.jackson.deserialization.read-date-timestamps-as-nanoseconds=false 

毫秒级时间戳会反序列化为 java.time.Instantjava.time.ZonedDateTime

指定

  • @JsonFormat: 输出想要的格式

    • @JsonFormat(pattern = ``"yyyy-MM-dd HH:mm:ss"``,timezone=``"GMT+8"``)
      @JsonFormat(without = JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS) //同上序列化设置
      
  • @DateTimeFormat:解析想要的格式

Jackson-枚举

objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, true);
spring.jackson.serialization.write-enums-using-index=true
spring.jackson.serialization.write-enums-using-to-string=true
  • 确定序列化枚举时使用 ordinary 还是 string
  • 反序列化时,无论使用ordinary 还是string 都能兼容并反序列化

Jackson-精度

@JsonSerialize(using = ToStringSerializer.class)
private Long id;

@JsonSerialize(using = ToStringSerializer.class)
private BigDecimal sallary;
  • 使用ToStringSerializer.class 进行序列化
  • 该注解可以用来对任意一个成员变量指定序列化类

Jackson-XML

部分老旧的接口任然在使用XML 序列化

依赖

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

使用注解调整格式

将字段作为标签属性或父元素属性
/**
* <name>xxx</name>
*   ==>
* <element nm="xxx"></element>
*/
@JacksonXmlProperty(isAttribute = true, localName = "nm")
private String name;
设置最外层标签

/**
* <MyType>xxx</MyType>
*  ==>
* <Hello xmlns="abcdefg"></Hello>
*/
@JacksonXmlRootElement(namespace = "abcdefg",localName = "Hello")
public class MyType {}

集合包装

/**
* JacksonXmlElementWrapper 时外层集合名称
* useWrapping = false 则会去掉外层大标签
*  
* <AAA>
*   <aaa></aaa>
*   <aaa></aaa> 
* </AAA>
*
*/
@JacksonXmlElementWrapper(localName = "AAA")
@JacksonXmlProperty(localName = "aaa")
private Collections<String> bbb;

直接暴露给父标签
/**
*<root><c>a</c></root>
* ==>
*<root></root>
*/
@JacksonXmlText;
private String c;

MyBatis-枚举

mybatis.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler
  • 枚举类型会被序列化为Ordinal 存储

关于枚举使用的一点建议

  • 虽然框架都提供了 使用 ordinal 反序列化的设置, 实际使用中会出现 几个问题
    • 枚举的 ordinal 和 枚举的顺序有关, 会被代码格式等工具破坏
    • java.lang.Enum 默认不提供 valueOf(int ordinal) 方法, 在三方框架不提供适配时, 使用成本高, 需要手动封装
    • 在提供给三方使用的SDK 或者jar 包里使用 枚举 更合适, 源代码不会被破坏