Jackson框架处理多态类

       

 有时,一张表里面存储的具体对象可能不一样,比如Person表,里面我存了man和woman,除去共有属性如姓名,年龄,性别等,可能还有一些属性不一样,针对man,woman又有不同的其他业务处理等,此时,新增或者修改接口我们都是用的同一个,如果传一个具体的对象避免不了要做各种判断逻辑,代码太冗余,那如何直接传顶层的抽象类(Person)呢?这就涉及到了一个多态的处理~ 这就是本文的主角Jackson框架

jackson允许配置多态类型处理,当进行反序列话时,JSON数据匹配的对象可能有多个子类型,为了正确的读取对象的类型,我们需要添加一些类型信息。可以通过下面几个注解来实现:

@JsonTypeInfo

作用于类/接口,被用来开启多态类型处理,对基类/接口和子类/实现类都有效

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "partner", visible = true, defaultImpl = Man.class)


属性介绍:

  • use:定义使用哪一种类型识别码,它有下面几个可选值:
    • JsonTypeInfo.Id.CLASS:使用完全限定类名做识别
    • JsonTypeInfo.Id.MINIMAL_CLASS:若基类和子类在同一包类,使用类名(忽略包名)作为识别码
    • JsonTypeInfo.Id.NAME:一个合乎逻辑的指定名称
    • JsonTypeInfo.Id.CUSTOM:自定义识别码,由@JsonTypeIdResolver对应,稍后解释
    • JsonTypeInfo.Id.NONE:不使用识别码
  • include(可选):指定识别码是如何被包含进去的,它有下面几个可选值:
    • JsonTypeInfo.As.PROPERTY:作为数据的兄弟属性(默认)
    • JsonTypeInfo.As.EXISTING_PROPERTY:作为POJO中已经存在的属性
    • JsonTypeInfo.As.EXTERNAL_PROPERTY:作为扩展属性
    • JsonTypeInfo.As.WRAPPER_OBJECT:作为一个包装的对象
    • JsonTypeInfo.As.WRAPPER_ARRAY:作为一个包装的数组
  • property(可选):制定识别码的属性名称
    此属性只有当:
    • useJsonTypeInfo.Id.CLASS(若不指定property则默认为@class)、JsonTypeInfo.Id.MINIMAL_CLASS(若不指定property则默认为@c)、JsonTypeInfo.Id.NAME(若不指定property默认为@type),
    • includeJsonTypeInfo.As.PROPERTYJsonTypeInfo.As.EXISTING_PROPERTYJsonTypeInfo.As.EXTERNAL_PROPERTY时才有效
  • defaultImpl(可选):如果类型识别码不存在或者无效,可以使用该属性来制定反序列化时使用的默认类型
  • visible(可选,默认为false):是否可见
    属性定义了类型标识符的值是否会通过JSON流成为反序列化器的一部分,默认为fale,也就是说,jackson会从JSON内容中处理和删除类型标识符再传递给JsonDeserializer。

@JsonSubTypes

作用于类/接口,用来列出给定类的子类,只有当子类类型无法被检测到时才会使用它,一般是配合@JsonTypeInfo在基类上使用,比如:
 

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "partner", visible = true, defaultImpl = Man.class)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Man.class, name = "wife"),
        @JsonSubTypes.Type(value = Woman.class, name = "husband")
})

@JsonTypeName

作用于子类,用来为多态子类指定类型标识符的值,使用该注解则可以不使用@JsonSubTypes
比如:

@JsonTypeName("husband")
public class Woman extends Person {...}
@JsonTypeName("wife")
public class Man extends Person {...}

demo: 

依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.13.3</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-annotations</artifactId>
   <version>2.13.3</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.13.3</version>
</dependency>
package com.cjian.jackson;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @Author: cjian
 * @Date: 2022/6/27 10:42
 * @Des:
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "partner", visible = true, defaultImpl = Man.class)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Man.class, name = "wife"),
        @JsonSubTypes.Type(value = Woman.class, name = "husband")
})
public abstract class Person {
    private String name;
    private int age;
    private String sex;
    private String partner;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getPartner() {
        return partner;
    }

    public void setPartner(String partner) {
        this.partner = partner;
    }
}

两个子类:

package com.cjian.jackson;

import com.fasterxml.jackson.annotation.JsonTypeName;

/**
 * @Author: cjian
 * @Date: 2022/6/27 10:44
 * @Des:
 */
public class Man extends Person {
    private String wife;

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    @Override
    public String toString() {
        return "Man{" +
                "wife='" + wife + '\'' +
                '}';
    }
}
package com.cjian.jackson;

import com.fasterxml.jackson.annotation.JsonTypeName;

/**
 * @Author: cjian
 * @Date: 2022/6/27 10:43
 * @Des:
 */
public class Woman extends Person {

    private String husband;

    public String getHusband() {
        return husband;
    }

    public void setHusband(String husband) {
        this.husband = husband;
    }

    @Override
    public String toString() {
        return "Woman{" +
                "husband='" + husband + '\'' +
                '}';
    }
}

测试:

package com.cjian.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @Author: cjian
 * @Date: 2022/6/29 10:30
 * @Des:
 */
public class Test {

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString1 = "{\"name\":\"cjian\",\"age\":28,\"sex\":\"男\",\"partner\":\"wife\",\"wife\":\"lili\"}";
        String jsonString2 = "{\"name\":\"lili\",\"age\":28,\"sex\":\"女\",\"partner\":\"husband\",\"husband\":\"cjian\"}";
        Person p1 = objectMapper.readValue(jsonString1, Man.class);
        Person p2 = objectMapper.readValue(jsonString2, Woman.class);
        System.out.println(p1);
        System.out.println(p2);
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值