抽象類使用Jackson序列化問題
抽象類使用Jackson序列化
當java對象中含List<Object>時,如果Object一個抽象類或接口,這里就會出現(xiàn)java多態(tài)的現(xiàn)象,比如List<Animal>, 如果Animal是個抽象類,并且有多個子類時,由于List中保存的Animal沒有明確指向具體的子類或實現(xiàn)類,json反序列化java對象時就會拋出提示:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException:Can not construct instance of Animal, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
可以使用@JsonTypeInfo與@JsonSubTypes來解決此類問題,通過注解,可以在序列化時,保存具體的類型信息到json中,當json反序列到java對象時,就可以根據(jù)具體類型信息創(chuàng)建正確的java對象。
@JsonTypeInfo
– indicates details of what type information to include in serialization 指出序列化包含的類型信息細節(jié)@JsonSubTypes
– indicates sub-types of the annotated type 指出被注解類型的子類@JsonTypeName
– defines a logical type name to use for annotated class 定義被注解類使用的邏輯名稱
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") }) public class Animal { public String name; public Animal(String name) { } } @JsonTypeName("dog") // 這里在子類中指定的type name必須和抽象類中注解@JsonSubTypes中name屬性指定的值保持一致 public class Dog extends Animal { public double barkVolume; public Dog(String name) { super(name); barkVolume = 0.5; } } @JsonTypeName("cat") public class Cat extends Animal { boolean likesCream; public int lives; public Cat(String name) { super(name); likesCream = true; lives = 10; } } @Test public void whenSerializingPolymorphic_thenCorrect() throws JsonProcessingException { Zoo.Dog dog = new Zoo.Dog("lacy"); Zoo zoo = new Zoo(dog); String result = new ObjectMapper() .writeValueAsString(zoo); assertThat(result, containsString("type")); assertThat(result, containsString("dog")); } 序列化zoo對象,結果如下: { "type":"dog", "name":"lacy", "barkVolume":0 } @Test public void whenDeserializingPolymorphic_thenCorrect() throws IOException { String json = "{\"name\":\"lacy\",\"type\":\"cat\"}"; Animal animal = new ObjectMapper().readerFor(Animal.class).readValue(json); assertEquals("lacy", animal.name); assertEquals(Cat.class, animal.getClass()); }
記一次jackson序列化Boolean的坑
@Data public class CouponTemplateDto { /** * 優(yōu)惠券類型id */ private Long couponTypeId; /** * 優(yōu)惠券模板id */ private Long couponTemplateId; /** * 用戶id */ private Long userId; /** * 優(yōu)惠券描述 */ private String description; /** * 面值,滿200減30,則此值為30 */ private BigDecimal value; /** * 從次日起,多少天可用 */ private Integer delayDays; /** * 從當日起,多少天可用 */ private Integer nowDays; /** * 滿多少可以減,滿200減30,則此值為200 */ private BigDecimal fullAmount; /** * 券號 */ private String couponNo; /** * 有效起始日期 */ private Date startTime; /** * 失效日期 */ private Date endTime; /** * 創(chuàng)建時間 */ private Date createTime; /** * 使用日期 */ private Date useTime; /** * 券使用狀態(tài):0-未使用 1-已使用 2-已過期 */ private Integer couponUseStatus; /** * 過期前多少天提醒,默認7天 */ private Integer overDueRemind; /** * 優(yōu)惠券標題 */ private String title; /** * 優(yōu)惠券是否能開始使用 */ // @JsonProperty("isStart") private Boolean start; /** * 優(yōu)惠券是否過期 */ // @JsonProperty("isEnd") private Boolean end; private Boolean getStart() { return startTime.before(new Date()); } private Boolean getEnd() { return endTime.before(new Date()); } }
我定義了一個這樣的類,我們項目用的是Spring Boot,默認底層采用的是jackson序列化,但是在使用中出了一個問題private Boolean start跟private Boolean end這兩個字段一直無法序列化
總結排查思路如下
1.是boolean還是Boolean,到底是基本數(shù)據(jù)類型還是包裝類,如果是基本數(shù)據(jù)類型的話(包裝類可以使用,但是不推薦),不要使用is開頭。我們可以看看阿里巴巴規(guī)范中的這段話
【強制】POJO類中的任何布爾類型的變量,都不要加 is,否則部分框架解析會引起序列化錯誤。
反例:定義為基本數(shù)據(jù)類型 boolean isSuccess;的屬性,它的方法也是 isSuccess(),RPC框架在反向解析的時候,“以為”對應的屬性名稱是 success,導致屬性獲取不到,進而拋出異常。
2.這個錯誤也是我犯的錯誤,我復寫了get方法,方法的訪問權限被設置成了private級別
解決方案:
- 加注解,@JsonProperty(“isEnd”)
- 將方法級別更正為public
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗功能
這篇文章主要介紹了SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12SpringBoot整合SpringSecurity和JWT和Redis實現(xiàn)統(tǒng)一鑒權認證
Spring Security是一個可以為Java應用程序提供全面安全服務的框架,同時它也可以輕松擴展以滿足自定義需求,本文主要介紹了SpringBoot整合SpringSecurity和JWT和Redis實現(xiàn)統(tǒng)一鑒權認證,感興趣的可以了解一下2023-11-11Java設計模式之觀察者模式observer?pattern詳解
這篇文章主要介紹了Java設計模式之觀察者模式observer?pattern詳解,當一個對象發(fā)生數(shù)據(jù)變化時,通知其他相關的一系列對象,接受到通知的對象根據(jù)該對象的變化進行相應處理以響應變化的過程,需要的朋友可以參考下2023-12-12SpringMVC用XML方式實現(xiàn)AOP的方法示例
這篇文章主要介紹了SpringMVC用XML方式實現(xiàn)AOP的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04SpringCloud feign微服務調用之間的異常處理方式
這篇文章主要介紹了SpringCloud feign微服務調用之間的異常處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06springmvc+shiro自定義過濾器的實現(xiàn)代碼
這篇文章主要介紹了springmvc+shiro自定義過濾器的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2018-10-10