jackson在springboot中的使用-自定义参数转换器
目录
- 要实现的功能
- 思路
- 关键代码
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 {@Beanpublic ObjectMapper objectMapper() {return createObjectMapper();}private ObjectMapper createObjectMapper(){ObjectMapper objectMapper = new ObjectMapper();SimpleModule simpleModule = new SimpleModule();/*** 序列化:对象=>jsonString*/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);/*** 反序列化:jsonString=>对象*///允许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> {@Overridepublic Date deserialize(JsonParser p, DeserializationContext ctxt) {try {return convert(p.getText());} catch (IOException e) {e.printStackTrace();}return null;}@Overridepublic 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> {@Overridepublic void serialize(Date value, JsonGenerator gen, SerializerProvider serializers){try {gen.writeString(convert(value));} catch (IOException e) {e.printStackTrace();}}@Overridepublic String convert(Date source) {return TimeUtil.time2Str(TimeUtil.date2Time(source),TimeFormat.DEFAULT);}
}
- 接口
/*** 枚举都要继承此接口,* @param 枚举实际值的数据类型*/
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());}
}
- 枚举的转换器
/*** json=>对象*/
@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;}@Overridepublic 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;}@Overridepublic JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {Class<T> targetClass = (Class<T>) ctxt.getContextualType().getRawClass();return new EnumDeserializer(targetClass);}
}
/*** 序列化,将enum枚举转为json* @author chenzy* @since 2019.12.19*/
@JsonComponent
public class EnumSerializer<T extends IEnum> extends JsonSerializer<T> {@Overridepublic 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("");}}
}
下面才是真正的转换器
/*** IEnum=>str*/
@Component
public class Enum2StrConverter<T extends IEnum<?>> implements ConditionalConverter,Converter<T, String>{private final ConversionService conversionService;protected Enum2StrConverter(ConversionService conversionService) {this.conversionService = conversionService;}@Overridepublic String convert(T source) {return source.getStr();}@Overridepublic 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;}
}
/*** str=>IEnum*/
@Component
public class Str2EnumConverte implements ConverterFactory<String, IEnum> {@Overridepublic <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;}@Overridepublic T convert(String source) {if (StringUtil.isBlank(source)) {return null;}return IEnum.getBean(source,enumType);}}
}
/*** @author chenzy* @since 2020-12-02*/
@Configuration
public class JacksonConfig implements WebMvcConfigurer {@Autowired private Str2EnumConverte str2EnumConverte;@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverterFactory(str2EnumConverte);}@Beanpublic ObjectMapper objectMapper() {return JsonUtil.getObjectMapper();}
}
以上代码比较简单,就没有写注释,有问题请留言。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
