返回顶部
首页 > 资讯 > 后端开发 > Python >jackson在springboot中的使用方式-自定义参数转换器
  • 584
分享到

jackson在springboot中的使用方式-自定义参数转换器

2024-04-02 19:04:59 584人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录SpringBoot jackson使用-自定义参数转换器要实现的功能思路关键代码Jackson自定义转换器@JSONDeserialize注解源码以日期类型为例自定义转换方法s

springboot jackson使用-自定义参数转换器

springboot中默认使用jackson,且实现了很多参数转换器,其中就有EnumToStrinGConverter和StringToEnumConverterFactory,用于字符串和枚举的互转。但是是根据枚举名称互转。

要实现的功能

  • 空属性我不希望转成json字符串
  • 日期对象我希望按照指定格式转换
  • 我存在多个枚举,类似public enum ChannelWayEnum { Bluetooth(0, "蓝牙"), NB(1, "NB-ioT"), G4(2, "自建4G"), Ali(3, "ali-4G");},用默认转换器无法转换。需要自定义转换。

思路

  • 覆盖默认注入的ObjectMapper,自己实现objectMapper,可设置忽略null字段
  • 自定义针对日期对象的Converter
  • 枚举需要实现接口IEnum,然后自定义针对IEnum接口的转换器

关键代码

注入ObjectMapper


@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        return createObjectMapper();
    }
    private ObjectMapper createObjectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        
        simpleModule.addSerializer(WashEnum.class, new WashEnumSerializer());
        simpleModule.addSerializer(IEnum.class, new EnumSerializer());
        simpleModule.addSerializer(Date.class, new DateSerializer());
        simpleModule.addSerializer(Boolean.class, new BooleanSerializer());
        //忽略null字段
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        
        //允许json属性名不使用双引号
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        //忽略不存在字段
        objectMapper.configure(DeserializationFeature.FaiL_ON_UNKNOWN_PROPERTIES, false);
        simpleModule.aDDDeserializer(String.class, new StringDeserializer());
        simpleModule.addDeserializer(Date.class, new DateDeserializer());
        simpleModule.addDeserializer(WashEnum.class, new WashEnumDeserializer());
        simpleModule.addDeserializer(Enum.class, new EnumDeserializer());//反序列化枚举,
        simpleModule.addDeserializer(Boolean.class, new BooleanDeserializer());
        objectMapper.reGISterModule(simpleModule);
        return objectMapper;
    }
}

日期对象的转换


@JsonComponent
public class DateDeserializer extends JsonDeserializer<Date> implements Converter<String, Date> {
    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) {
        try {
            return convert(p.getText());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    @Override
    public Date convert(String source) {
        if (StringUtil.isBlank(source)) {
            return null;
        }
        return TimeUtil.toDate(TimeUtil.str2Time(source, TimeFORMat.DEFAULT));
    }
}
@JsonComponent
public class DateSerializer extends JsonSerializer<Date> implements Converter<Date,String> {
    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers){
        try {
            gen.writeString(convert(value));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public String convert(Date source) {
        return TimeUtil.time2Str(TimeUtil.date2Time(source),TimeFormat.DEFAULT);
    }
}

接口



public interface IEnum<V> {
    //枚举实际值
    V getValue();
    static<T extends IEnum> T getBean(String value,Class<T> tClass){
        if (StringUtil.isBlank(value)){
            return null;
        }
        for (T enumObj : tClass.getEnumConstants()) {
            if (value.equals(enumObj.getValue().toString())) {
                return enumObj;
            }
        }
        return null;
    }
    default String getStr(){
        return String.valueOf(getValue());
    }
}

枚举的转换器



@JsonComponent
public class EnumDeserializer<T extends IEnum> extends JsonDeserializer<T> implements ContextualDeserializer{
    private Class<T> targetClass = null;
    public EnumDeserializer() {
    }
    public EnumDeserializer(Class<T> targetClass) {
        this.targetClass = targetClass;
    }
    @Override
    public T deserialize(JsonParser p, DeserializationContext ctxt) {
//        if(targetClass!=null&&IEnum.class.isAssignableFrom(targetClass)){
            try {
                return IEnum.getBean(p.getText(),targetClass);
            } catch (IOException e) {
                e.printStackTrace();
            }
//        }
        return null;
    }
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
        Class<T> targetClass = (Class<T>) ctxt.getContextualType().getRawClass();
        return new EnumDeserializer(targetClass);
    }
}

@JsonComponent
public class EnumSerializer<T extends IEnum> extends JsonSerializer<T> {
    @Override
    public void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        Optional<T> data = Optional.of(value);
        if (data.isPresent()) {//非空
            gen.writeObject(data.get().getValue());
        } else {
//            gen.writeString("");
        }
    }
}

下面才是真正的转换器



@Component
public class Enum2StrConverter<T extends IEnum<?>> implements ConditionalConverter,Converter<T, String>{
    private final ConversionService conversionService;
    protected Enum2StrConverter(ConversionService conversionService) {
        this.conversionService = conversionService;
    }
    @Override
    public String convert(T source) {
        return source.getStr();
    }
    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        for (Class<?> interfaceType : ClassUtils.getAllInterfacesForClassAsSet(sourceType.getType())) {
            if (this.conversionService.canConvert(TypeDescriptor.valueOf(interfaceType), targetType)) {
                return false;
            }
        }
        return true;
    }
}

@Component
public class Str2EnumConverte implements ConverterFactory<String, IEnum> {
    @Override
    public <T extends IEnum> Converter<String, T> getConverter(Class<T> targetType) {
        return new Str2Enum(targetType);
    }
    private static class Str2Enum<T extends IEnum> implements Converter<String, T> {
        private final Class<T> enumType;
        public Str2Enum(Class<T> enumType) {
            this.enumType = enumType;
        }
        @Override
        public T convert(String source) {
            if (StringUtil.isBlank(source)) {
                return null;
            }
            return IEnum.getBean(source,enumType);
        }
    }
}

@Configuration
public class JacksonConfig  implements WEBmvcConfigurer {
    @Autowired private Str2EnumConverte str2EnumConverte;
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(str2EnumConverte);
    }
    @Bean
    public ObjectMapper objectMapper() {
        return JsonUtil.getObjectMapper();
    }
}

Jackson自定义转换器

使用jackson进行json和java bean转换时,可以使用注解自定义转换器进行转换。

@JsonDeserialize注解源码

方法注释中写了,using 方法是作用在method上的。


 
package com.fasterxml.jackson.databind.annotation; 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.util.Converter;
 

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@com.fasterxml.jackson.annotation.JacksonAnnotation
public @interface JsonDeserialize
{
    // // // Annotations for explicitly specifying deserialize/builder
 
    
    @SuppressWarnings("rawtypes") // to work around jdk8 bug wrt Class-valued annotation properties
    public Class<? extends JsonDeserializer> using()
        default JsonDeserializer.None.class;
 
    
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends JsonDeserializer> contentUsing()
        default JsonDeserializer.None.class;
 
    
    public Class<? extends KeyDeserializer> keyUsing()
        default KeyDeserializer.None.class;
 
    
    public Class<?> builder() default Void.class;
 
    // // // Annotations for specifying intermediate Converters (2.2+)
    
    
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends Converter> converter() default Converter.None.class;
 
    
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends Converter> contentConverter() default Converter.None.class;
        
    // // // Annotations for explicitly specifying deserialization type
    // // // (which is used for choosing deserializer, if not explicitly
    // // // specified
 
    
    public Class<?> as() default Void.class;
 
    
    public Class<?> keyAs() default Void.class;
 
    
    public Class<?> contentAs() default Void.class;
}
 

以日期类型为例


@JsonDeserialize(using= DateJsonDeserializer.class) // Json ==> Bean,需要写到Setter方法上
public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}
 
@JsonSerialize(using= DateJsonSerializer.class) // Bean ==> Json,需要写到Getter方法上
public Date getCreateTime() {
    return createTime;
}

自定义转换方法


public class DateJsonDeserializer extends JsonDeserializer<Date> {
    public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public Date deserialize(com.fasterxml.jackson.core.JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, com.fasterxml.jackson.core.JsonProcessingException {
 
        try {
            if(jsonParser!=null&&StringUtils.isNotEmpty(jsonParser.getText())){
                return format.parse(jsonParser.getText());
            }else {
                return null;
            }
 
        } catch(Exception e) {
            System.out.println(e.getMessage());
            throw new RuntimeException(e);
        }
    } 
} 
 
public class DateJsonSerializer extends JsonSerializer<Date> {
    public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(format.format(date));
    } 
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: jackson在springboot中的使用方式-自定义参数转换器

本文链接: https://lsjlt.com/news/137768.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作