Jackson自定義序列化與反序列化注解詳解
前言
某些場(chǎng)景下,我們使用Jackson對(duì)數(shù)據(jù)進(jìn)行序列化或反序列化的時(shí)候,需要對(duì)某些數(shù)據(jù)進(jìn)行特殊處理,比如,不同的場(chǎng)景下,對(duì)數(shù)字的精度要求不同,此時(shí)如果僅僅使用原始的@JsonDeserialize和@JsonSerialize注解,不能滿足我們的需求,如果每種精度都寫一個(gè)獨(dú)立的處理類,無(wú)疑增加了代碼的復(fù)雜度。
我們可以看到@JsonDeserialize和@JsonSerialize都支持注解標(biāo)注
于是可以自己定義一個(gè)注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JsonDeserialize(using = DecimalFormatJsonDeserializer.class) public @interface DecimalFormat{ int scale() default 2; }
僅僅加上@JsonDeserialize注解的話,會(huì)發(fā)現(xiàn)Jackson在反序列時(shí),并不會(huì)走到我們定義的DecimalFormatJsonDeserializer類中,還需要加上一個(gè)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)前反序列化的對(duì)象類型 Class<?> clazz = jsonParser.getCurrentValue().getClass(); BigDecimal decimalValue = jsonParser.getDecimalValue(); Field declaredField; try { // 通過(guò)字段名稱獲取對(duì)應(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; } }
測(cè)試代碼
@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對(duì)象 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)); } }
測(cè)試代碼
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java常見(jiàn)延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié)
Java延遲隊(duì)列(DelayQueue)是Java并發(fā)包中的一個(gè)類,它實(shí)現(xiàn)了BlockingQueue接口,且其中的元素必須實(shí)現(xiàn)Delayed接口,延遲隊(duì)列中的元素按照延遲時(shí)間的長(zhǎng)短進(jìn)行排序,本文給大家介紹了Java常見(jiàn)延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié),需要的朋友可以參考下2024-03-03Java中的自動(dòng)裝箱與自動(dòng)拆箱的實(shí)現(xiàn)
自動(dòng)裝箱和自動(dòng)拆箱使得我們?cè)谑褂没緮?shù)據(jù)類型時(shí)更加方便,同時(shí)也提高了代碼的可讀性和健壯性,本文將詳細(xì)介紹Java中的自動(dòng)裝箱和自動(dòng)拆箱機(jī)制,感興趣的可以了解一下2023-08-08Mybatis查不到數(shù)據(jù)查詢返回Null問(wèn)題
mybatis突然查不到數(shù)據(jù),查詢返回的都是Null,但是 select count(*) from xxx查詢數(shù)量,返回卻是正常的。好多朋友遇到這樣的問(wèn)題不知所措,下面小編通過(guò)本教程簡(jiǎn)單給大家說(shuō)明下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異步問(wèn)題記錄
這篇文章主要介紹了Spring Cloud Gateway調(diào)用Feign異步問(wèn)題記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04