Jackson自定義序列化與反序列化注解詳解
前言
某些場景下,我們使用Jackson對數(shù)據(jù)進(jìn)行序列化或反序列化的時候,需要對某些數(shù)據(jù)進(jìn)行特殊處理,比如,不同的場景下,對數(shù)字的精度要求不同,此時如果僅僅使用原始的@JsonDeserialize和@JsonSerialize注解,不能滿足我們的需求,如果每種精度都寫一個獨(dú)立的處理類,無疑增加了代碼的復(fù)雜度。
我們可以看到@JsonDeserialize和@JsonSerialize都支持注解標(biāo)注
于是可以自己定義一個注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JsonDeserialize(using = DecimalFormatJsonDeserializer.class) public @interface DecimalFormat{ int scale() default 2; }
僅僅加上@JsonDeserialize注解的話,會發(fā)現(xiàn)Jackson在反序列時,并不會走到我們定義的DecimalFormatJsonDeserializer類中,還需要加上一個Jackson的注解繼承注解@JacksonAnnotationsInside
自定義反序列化注解及實(shí)現(xiàn)
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JacksonAnnotationsInside @JsonDeserialize(using = DecimalFormatJsonDeserializer.class) public @interface DecimalFormat{ int scale() default 2; }
編寫反序列化實(shí)現(xiàn)
public static class DecimalFormatJsonDeserializer extends JsonDeserializer<Double> { @Override public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { // 獲取當(dāng)前反序列化的對象類型 Class<?> clazz = jsonParser.getCurrentValue().getClass(); BigDecimal decimalValue = jsonParser.getDecimalValue(); Field declaredField; try { // 通過字段名稱獲取對應(yīng)字段 // 需考慮繼承情況 declaredField = clazz.getDeclaredField(jsonParser.getCurrentName()); } catch (NoSuchFieldException e) { return decimalValue.doubleValue(); } // 獲取注解 DecimalFormat annotation = declaredField.getAnnotation(DecimalFormat.class); if (annotation == null) { return decimalValue.doubleValue(); } int scale = annotation.scale(); if (decimalValue != null) { return decimalValue.setScale(scale, RoundingMode.HALF_UP).doubleValue(); } return null; } }
測試代碼
@Data static class TestVo { @DecimalFormat(scale = 1) private Double amount; private String name; }
public static void main(String args[]) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); TestVo testVo = objectMapper.readValue("{\"amount\":3.5576,\"name\":\"young\"}", TestVo.class); System.out.println(testVo); // TestVo(amount=3.6, name=young) }
自定義序列化注解及實(shí)現(xiàn)
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JacksonAnnotationsInside @JsonSerialize(using = DecimalFormatJsonSerializer.class) public @interface DecimalSerializerFormat { String pattern() default "0.0000"; }
編寫序列化實(shí)現(xiàn)
public class DecimalFormatJsonSerializer extends JsonSerializer<BigDecimal> { @Override public void serialize(BigDecimal bigDecimal, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { JsonStreamContext outputContext = jsonGenerator.getOutputContext(); // 獲取當(dāng)前class對象 Class<?> clazz = outputContext.getCurrentValue().getClass(); // 獲取當(dāng)前屬性名 String fieldName = outputContext.getCurrentName(); // 獲取當(dāng)前屬性的field Field field = FieldUtils.getDeclaredField(clazz, fieldName, true); // 獲取當(dāng)前屬性的注解 DecimalSerializerFormat annotation = field.getAnnotation(DecimalSerializerFormat.class); if (annotation == null) { return; } String pattern = annotation.pattern(); DecimalFormat decimalFormat = new DecimalFormat(pattern); jsonGenerator.writeString(decimalFormat.format(bigDecimal)); } }
測試代碼
public static void main(String[] args) throws JsonProcessingException { Test test = new Test(); test.setDecimal(BigDecimal.ONE); ObjectMapper objectMapper = new ObjectMapper(); String s = objectMapper.writeValueAsString(test); System.out.println(s); // {"decimal":"1.0000"} } @Data static class Test{ @DecimalSerializerFormat private BigDecimal decimal; }
到此這篇關(guān)于Jackson自定義序列化與反序列化注解詳解的文章就介紹到這了,更多相關(guān)Jackson序列化與反序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java常見延遲隊列的實(shí)現(xiàn)方案總結(jié)
Java延遲隊列(DelayQueue)是Java并發(fā)包中的一個類,它實(shí)現(xiàn)了BlockingQueue接口,且其中的元素必須實(shí)現(xiàn)Delayed接口,延遲隊列中的元素按照延遲時間的長短進(jìn)行排序,本文給大家介紹了Java常見延遲隊列的實(shí)現(xiàn)方案總結(jié),需要的朋友可以參考下2024-03-03Mybatis查不到數(shù)據(jù)查詢返回Null問題
mybatis突然查不到數(shù)據(jù),查詢返回的都是Null,但是 select count(*) from xxx查詢數(shù)量,返回卻是正常的。好多朋友遇到這樣的問題不知所措,下面小編通過本教程簡單給大家說明下2016-08-08Java中Aspose組件進(jìn)行多文檔間的轉(zhuǎn)換方法總結(jié)
在本篇文章里我們給大家分享了關(guān)于Java中Aspose組件進(jìn)行多文檔間的轉(zhuǎn)換方法內(nèi)容,需要的朋友們學(xué)習(xí)下吧。2019-02-02Spring Cloud Gateway調(diào)用Feign異步問題記錄
這篇文章主要介紹了Spring Cloud Gateway調(diào)用Feign異步問題記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04