抽象类使用Jackson序列化问题

 更新时间:2023年01月01日 08:24:38   作者:追梦菜鸟  
这篇文章主要介绍了抽象类使用Jackson序列化问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

抽象类使用Jackson序列化

当java对象中含List<Object>时,如果Object一个抽象类或接口,这里就会出现java多态的现象,比如List<Animal>, 如果Animal是个抽象类,并且有多个子类时,由于List中保存的Animal没有明确指向具体的子类或实现类,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对象时,就可以根据具体类型信息创建正确的java对象。

  • @JsonTypeInfo – indicates details of what type information to include in serialization 指出序列化包含的类型信息细节
  • @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 {
    /**
     * 优惠券类型id
     */
    private Long couponTypeId;
    /**
     * 优惠券模板id
     */
    private Long couponTemplateId;
    /**
     * 用户id
     */
    private Long userId;

    /**
     * 优惠券描述
     */
    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;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 使用日期
     */
    private Date useTime;

    /**
     * 券使用状态:0-未使用 1-已使用 2-已过期
     */
    private Integer couponUseStatus;
    /**
     * 过期前多少天提醒,默认7天
     */
    private Integer overDueRemind;
    /**
     * 优惠券标题
     */
    private String title;

    /**
     * 优惠券是否能开始使用
     */
//    @JsonProperty("isStart")
    private Boolean start;
    /**
     * 优惠券是否过期
     */
//    @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,到底是基本数据类型还是包装类,如果是基本数据类型的话(包装类可以使用,但是不推荐),不要使用is开头。我们可以看看阿里巴巴规范中的这段话

【强制】POJO类中的任何布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。

反例:定义为基本数据类型 boolean isSuccess;的属性,它的方法也是 isSuccess(),RPC框架在反向解析的时候,“以为”对应的属性名称是 success,导致属性获取不到,进而抛出异常。

2.这个错误也是我犯的错误,我复写了get方法,方法的访问权限被设置成了private级别

解决方案:

  • 加注解,@JsonProperty(“isEnd”)
  • 将方法级别更正为public

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解析Spring事件发布与监听机制

    解析Spring事件发布与监听机制

    本篇文章给大家介绍Spring事件发布与监听机制,通过 ApplicationEvent 事件类和 ApplicationListener 监听器接口,可以实现 ApplicationContext 事件发布与处理,需要的朋友参考下吧
    2021-06-06
  • SpringCloud+Tornado基于jwt实现请求安全校验功能

    SpringCloud+Tornado基于jwt实现请求安全校验功能

    这篇文章主要介绍了SpringCloud+Tornado基于jwt实现请求安全校验,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Java Map所有的值转为String类型

    Java Map所有的值转为String类型

    本文主要介绍了Java Map所有的值转为String类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • SpringBoot整合SpringSecurity和JWT和Redis实现统一鉴权认证

    SpringBoot整合SpringSecurity和JWT和Redis实现统一鉴权认证

    Spring Security是一个可以为Java应用程序提供全面安全服务的框架,同时它也可以轻松扩展以满足自定义需求,本文主要介绍了SpringBoot整合SpringSecurity和JWT和Redis实现统一鉴权认证,感兴趣的可以了解一下
    2023-11-11
  • Java设计模式之观察者模式observer pattern详解

    Java设计模式之观察者模式observer pattern详解

    这篇文章主要介绍了Java设计模式之观察者模式observer pattern详解,当一个对象发生数据变化时,通知其他相关的一系列对象,接受到通知的对象根据该对象的变化进行相应处理以响应变化的过程,需要的朋友可以参考下
    2023-12-12
  • SpringMVC用XML方式实现AOP的方法示例

    SpringMVC用XML方式实现AOP的方法示例

    这篇文章主要介绍了SpringMVC用XML方式实现AOP的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • SpringCloud feign微服务调用之间的异常处理方式

    SpringCloud feign微服务调用之间的异常处理方式

    这篇文章主要介绍了SpringCloud feign微服务调用之间的异常处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring Boot 自动配置的实现

    Spring Boot 自动配置的实现

    这篇文章主要介绍了Spring Boot 自动配置的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • springmvc+shiro自定义过滤器的实现代码

    springmvc+shiro自定义过滤器的实现代码

    这篇文章主要介绍了springmvc+shiro自定义过滤器的实现方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-10-10
  • 解决jar包rar压缩后无法运行问题

    解决jar包rar压缩后无法运行问题

    这篇文章主要介绍了解决jar包rar压缩后无法运行问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05

最新评论