当前位置:网站首页>One article explains Jackson configuration information in detail

One article explains Jackson configuration information in detail

2022-06-24 15:51:00 Boundless II

background

1.1 problem

Spring Boot When dealing with serialization and deserialization of objects , By default, the built-in JackSon To configure . Use the frame default , We usually face the following problems :
  1. Date Return date format ( It is not recommended to use Date, But old projects should be compatible ), with T, Such as 2018-05-15T24:59:59:
  1. LocalDate The returned Date object is an array ( The framework inherits WebMvcConfigurationSupport);
  1. LocalDateTime Time conversion failed ;
  1. Defines the date type , Such as LocalDate, Front end docking (post/get), If you pass in a date string ("2022-05-05"), Will be submitted to the String Convert to LocalDate Failure ;
  1. return long Type data , front end js There is accuracy problem , Conversion required ;
  1. Some special objects need special business transformation , Such as encryption and decryption ;

1.2 Solution

For the above problems , There are many solutions . Because the underlying framework uniformly configures different implementation modes of interception classes , There will still be differences , This article mainly explains that in different configuration scenarios , Customize Jackson Some considerations for configuration and reasons for differentiation :
In order to solve special objects ( Such as date ) Serialization and deserialization of , Common schemes are as follows :
  1. For a particular specific object , Use annotations on objects , Such as :
@JsonSerialize(using= JsonDateSerializer.class)
private Date taskEndTime;

@ApiModelProperty(value = " Inspection date ")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate checkDate;
  1. Re actualize WebMvcConfigurer Interface , Customize JackSon To configure .
  1. Inherit WebMvcConfigurationSupport class , Customize JackSon To configure .

1.3 In particular

  • programme 1 The pattern of , Annotate the corresponding variable , It can solve the problem , But the code is seriously duplicated , Not elegant ;
  • Realization WebMvcConfigurer Interface and inheritance WebMvcConfigurationSupport class , yes Spring Boot It provides two modes for developers to make unified global configuration classes , Notice the difference between the two modes , See the following chapters for details ( Two different modes , Improper use , The configuration will not take effect );

Customize Jackson

  1. JackSon Configuration instructions

Customize a Jackson Configuration information , Need to know Jackson Some configuration standards for , Such as :
// Ignored in deserialization  json  There is but  Java  Object does not exist 

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,

false);

// The date format defaults to  yyyy-MM-dd'T'HH:mm:ss.SSSZ , For example, if a class has private Date date; This date attribute , Serialized as :{"date" : 1413800730456}, If not true, Then for {"date" : "2014-10-20T10:26:06.604+0000"}

mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);

// Ignore the value... When serializing  null  Properties of 

mapper.setSerializationInclusion(Include.NON_NULL);

// Ignore properties with default values 

mapper.setDefaultPropertyInclusion(Include.NON_DEFAULT);

//  Beautify the output 

mapper.enable(SerializationFeature.INDENT_OUTPUT);

//  Allow serialization of empty POJO class 

// ( Otherwise, an exception will be thrown )

mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

//  hold java.util.Date, Calendar Output to digital ( Time stamp )

mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

//  Don't throw an exception when you encounter an unknown property 

mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

//  mandatory JSON  An empty string ("") Convert to null The object is worth :

mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

//  stay JSON It is allowed that C/C++  Comments on styles ( Nonstandard , Default disabled )

mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);

//  Allow field names without quotes ( Nonstandard )

mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

//  Single quotation marks are allowed ( Nonstandard )

mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

//  Mandatory escape is not ASCII character 

mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);

//  Wrap the content into a JSON attribute , The attribute name is from @JsonRootName Annotation assignment 

mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

// Serializing enumerations starts with toString() To output , Default false, That is to say, by default name() To output 

mapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);

// serialize Map When the key Sort operations , Default false

mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);

// serialize char[] Time and space json Array output , Default false

mapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
View Code
  1. Realization WebMvcConfigurer Interface

Rewrite a ObjectMapper, Replace the system default bean, You can implement the interface in post Request mode , Object serialization and deserialization define the configuration information .
Rewrite Jackson after , It doesn't deal with get When asked , Serialization of special objects such as dates ; in the light of get request , Write the serialization rule function of the object , By implementing addFormatters() Interface , Scalable support ;

To write LocalDateTime Conversion function

/**
 * java 8 LocalDateTime converter 
 *
 * @author wangling
 */
public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public LocalDateTime parse(String text, Locale locale) throws ParseException {
        return LocalDateTime.parse(text, formatter);
    }

    @Override
    public String print(LocalDateTime object, Locale locale) {
        return formatter.format(object);
    }
}

To write LocalDate Conversion function

/**
 * java 8 localDate converter 
 *
 * @author wangling
 */
public class LocalDateFormatter implements Formatter<LocalDate> {
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public LocalDate parse(String text, Locale locale) throws ParseException {
        return LocalDate.parse(text, formatter);
    }

    @Override
    public String print(LocalDate object, Locale locale) {
        return formatter.format(object);
    }
}

To write Jackson To configure

Write a custom ObjectMapper bean object , Set priority to replace default bean.
/**
 *  Project global configuration class 
 * 
 * @author wangling
 * @date 2022/06/10
 */
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

  @Override
  public void addFormatters(FormatterRegistry registry) {
    registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
    registry.addFormatterForFieldType(LocalDateTime.class, new LocalDateTimeFormatter());
  }

  @Bean
  @Primary
  public ObjectMapper ObjectMapper() {
    String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    String dateFormat = "yyyy-MM-dd";
    String timeFormat = "HH:mm:ss";
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    //  serialize 
    javaTimeModule.addSerializer(
        LocalDateTime.class,
        new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addSerializer(
        LocalDate.class,
        new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addSerializer(
        LocalTime.class,
        new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addSerializer(
        Date.class,
        new DateSerializer(false, new SimpleDateFormat(dateTimeFormat)));

    //  Deserialization 
    javaTimeModule.addDeserializer(
        LocalDateTime.class,
        new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addDeserializer(
        LocalDate.class,
        new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addDeserializer(
        LocalTime.class,
        new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
      @SneakyThrows
      @Override
      public Date deserialize(JsonParser jsonParser, DeserializationContext dc) {
        String text = jsonParser.getText().trim();
        SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat);
        return sdf.parse(text);
      }
    });
    javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
    javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
  }
}
  1. WebMvcConfigurationSupport class

To write Jackson To configure

Rewrite Jackson after , It doesn't deal with get When asked , Serialization of special objects such as dates ; in the light of get request , Write the serialization rule function of the object , By implementing addFormatters() Interface , Scalable support ;
Write custom configuration Jackson Information , Need to rewrite extendMessageConverters Method . Specific technical details , Please refer to the documentation 《 Spring Boot Realization WebMvcConfigurationSupport Lead to custom JSON The time return format does not take effect 》
/**
 *  Project global configuration class 
 * 
 * @author wangling
 * @date 2022/06/10
 */
@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport {

  @Override
  protected void addFormatters(FormatterRegistry registry) {
    //  be used for get  Global format date conversion 
    registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
    registry.addFormatterForFieldType(LocalDateTime.class, new LocalDateTimeFormatter());
  }

  @Override
  protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    //  Replace the frame default JackSon To configure   be used for post  Global format date conversion ,long Turn the string 
    MappingJackson2HttpMessageConverter jackson2HttpMessageConverter =
        new MappingJackson2HttpMessageConverter();
    jackson2HttpMessageConverter.setObjectMapper(ObjectMapper());
    //  Based on order , First, execute the customized 
    converters.add(0, jackson2HttpMessageConverter);
  }


  private ObjectMapper ObjectMapper() {
    String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    String dateFormat = "yyyy-MM-dd";
    String timeFormat = "HH:mm:ss";
    ObjectMapper objectMapper = new ObjectMapper();
    // Ignore empty Bean turn json Error of 
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    // Ignore   stay json There is... In the string , But there is no corresponding attribute in the object , Prevent mistakes .
    //  for example json There are more fields in the data , There is no such field in the object . If you set true, Throw an exception , Because the field does not correspond to ;false Then ignore the extra fields , The default value is null, Deserialize other fields successfully 
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    //  serialize 
    javaTimeModule.addSerializer(
        LocalDateTime.class,
        new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addSerializer(
        LocalDate.class,
        new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addSerializer(
        LocalTime.class,
        new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addSerializer(
        Date.class,
        new DateSerializer(false, new SimpleDateFormat(dateTimeFormat)));

    //  Deserialization 
    javaTimeModule.addDeserializer(
        LocalDateTime.class,
        new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addDeserializer(
        LocalDate.class,
        new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addDeserializer(
        LocalTime.class,
        new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
      @SneakyThrows
      @Override
      public Date deserialize(JsonParser jsonParser, DeserializationContext dc) {
        String text = jsonParser.getText().trim();
        SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat);
        return sdf.parse(text);
      }
    });
    javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
    javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
  }
}
View Code

WebMvcConfigurer And WebMvcConfigurationSupport Related knowledge

  1. Basic knowledge points

Spring Of WebMvcConfigurer Interfaces provide many ways for developers to customize SpringMVC Configuration of .
WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware. More and more customized configurations are supported ,WebMvcConfigurerAdapter There are ways , This class also has . This kind of annotation content is translated : This is to provide MVC Java config The main classes configured behind . Usually by putting @EnableWebMvc Added to the application @Configuration Class . Another more advanced option is to extend directly from this class and rewrite methods as needed , Remember to add subclasses @Configuration, Rewrite with @Bean We should also add @Bean.
  1. Precautions for use

          Reference documents : 《 Reason for interception failure 》
  1. Realization WebMvcConfigurer: Will not cover WebMvcAutoConfiguration Configuration of
  1. Realization WebMvcConfigurer+ annotation @EnableWebMvc: Will be covered WebMvcAutoConfiguration Configuration of
  1. Inherit WebMvcConfigurationSupport: Will be covered WebMvcAutoConfiguration Configuration of
  1. Inherit DelegatingWebMvcConfiguration: Will be covered WebMvcAutoConfiguration Configuration of
  1. Recommended use mode

  1. It's not necessary , It's best to avoid WebMvcConfigurer,WebMvcConfigurationSupport Use... Simultaneously in a project ;
  1. Intercept configuration for security , Recommended for the project WebMvcConfigurer Interface for global configuration ;
  1. date , It is suggested to use LocalDate, Replace historical Date data type ;
 
原网站

版权声明
本文为[Boundless II]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241447430820.html