我们在spring框架中使用jackson json时,有时需要自定义里面的objectMapper,很多教程选择直接自己定一个ObjectMapper Bean来实现自定义,实际上,spring提供了Jackson2ObjectMapperBuilderCustomizer来帮助我们自定义,这样就不用覆盖掉spring对objetcMapper默认的一些配置了。
只要将我们自定义的Customizer声明成bean,他就可以自动的对object Mapper进行配置了。

下面是配置,包括 修改默认命名策略,日期格式,Long类型转换等:


/**
 * @author 
 *  */
@Slf4j
@Component
public class MyJackson2ObjectMapperBuilderCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        log.info("My Jackson2ObjectMapperBuilderCustomizer customize!");
        jacksonObjectMapperBuilder.failOnUnknownProperties(false);
        jacksonObjectMapperBuilder.failOnEmptyBeans(false);
// 这里会将json的格式改成        SNAKE_CASE,影响@ResponseBody的返回值@RequestBody的读取
        jacksonObjectMapperBuilder.propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

// 忽略一些不能被json序列化的类,这些类不存在时就不用管它,存在的话就忽略序列化
        addIgnoreClass("org.springframework.validation.BindingResult", jacksonObjectMapperBuilder);
        addIgnoreClass("jakarta.servlet.http.HttpServletRequest", jacksonObjectMapperBuilder);
        addIgnoreClass("jakarta.servlet.http.HttpServletResponse", jacksonObjectMapperBuilder);
        addIgnoreClass("org.springframework.web.multipart.MultipartFile", jacksonObjectMapperBuilder);

        JavaTimeModule javaTimeModule = new JavaTimeModule();
        SimpleModule simpleModule = new SimpleModule();
        javaTimeModule.addDeserializer(LocalDateTime.class, new MyLocalDateTimeDeserializer());
        javaTimeModule.addSerializer(LocalDateTime.class, new MyLocalDateTimeSerializer());
        // 防止javascript中long类型太大时丢失精度
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        jacksonObjectMapperBuilder.modules(javaTimeModule, simpleModule); // 解决 LocalDateTime 的序列化
    }


    private static void addIgnoreClass(String className, Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        try {
            Class<?> clazz = Class.forName(className);
            jacksonObjectMapperBuilder.mixIn(clazz, IgnoreTypeMinIn.class);
        } catch (ClassNotFoundException e) {
            // ignore
        }
    }
}

import com.fasterxml.jackson.annotation.JsonIgnoreType;

/**
 * @author 
 */
@JsonIgnoreType
public class IgnoreTypeMinIn {
}


/**
 * LocalDateTime反序列化规则
 * <p>
 * 会将毫秒级时间戳反序列化为LocalDateTime
 */
public class MyLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

    public static final MyLocalDateTimeDeserializer INSTANCE = new MyLocalDateTimeDeserializer();

    private static final LocalDateTimeDeserializer DEFAULT_DESERIALIZER =
            new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
            return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
        }
        return DEFAULT_DESERIALIZER.deserialize(p, ctxt);
    }
}


/**
 * LocalDateTime序列化规则
 * <p>
 * 会将LocalDateTime序列化为毫秒级时间戳
 */
public class MyLocalDateTimeSerializer extends StdSerializer<LocalDateTime> implements ContextualSerializer {

    public static final MyLocalDateTimeSerializer INSTANCE = new MyLocalDateTimeSerializer();

    public MyLocalDateTimeSerializer() {
        super(LocalDateTime.class);
    }

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        JsonFormat.Value format = findFormatOverrides(prov, property, handledType());
        // 有自定义format,就按照format定义的反序列化
        if (format != null && (format.hasPattern() || format.hasTimeZone() || format.hasLocale())) {
            return LocalDateTimeSerializer.INSTANCE.createContextual(prov, property);
        }

        // 没有自定义format,格式化成时间戳
        return MyLocalDateTimeSerializer.INSTANCE;
    }
}


GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐