• jackson允许配置多态类型处理,当进行反序列话时,JSON数据匹配的对象可能有多个子类型,为了正确的读取对象的类型,我们需要添加一些类型信息。可以通过下面几个注解来实现:
  • @JsonTypeInfo 作用于类/接口,被用来开启多态类型处理,对基类/接口和子类/实现类都有效
  • @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "name") 这个注解有一些属性:
  • 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 = "typeName")  
@JsonSubTypes({@JsonSubTypes.Type(value=Sub1.class,name = "sub1"),@JsonSubTypes.Type(value=Sub2.class,name = "sub2")})

@JsonSubTypes的值是一个@JsonSubTypes.Type[]数组,里面枚举了多态类型(value对应子类)和类型的标识符值(name对应@JsonTypeInfo中的property标识名称的值,此为可选值,若不制定需由@JsonTypeName在子类上制定)

  • @JsonTypeName
  • 作用于子类,用来为多态子类指定类型标识符的值
  • 比如:

  • @JsonTypeName(value = "sub1")


示例

  • 基类:


@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value= Test.RoleUser.class,name = "role"),@JsonSubTypes.Type(value= Test.TokenUser.class,name = "token")})
public abstract class AbstractBaseEntity {

     private String userName;
     private String password;


    public String getUserName() {
        return userName;
    }

    public AbstractBaseEntity setUserName(String userName) {
        this.userName = userName;
        return this;
    }

    public String getPassword() {
        return password;
    }

    public AbstractBaseEntity setPassword(String password) {
        this.password = password;
        return this;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("AbstractBaseEntity{");
        sb.append("userName='").append(userName).append('\'');
        sb.append(", password='").append(password).append('\'');
        sb.append('}');
        return sb.toString();
    }
}
  • 测试类


import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author micocube
 * projectName: utils4j
 * packageName: jackson
 * email: ldscube@gmail.com
 * createTime: 2019-07-05 11:23
 * version: 0.1
 * description:
 */
public class Test {

    # 子类
    public static class TokenUser extends AbstractBaseEntity {

        private String token;


        public String getToken() {
            return token;
        }

        public TokenUser setToken(String token) {
            this.token = token;
            return this;
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer("TokenUser{");
            sb.append("token='").append(token).append('\'');
            sb.append('}');
            sb.append(super.toString());
            return sb.toString();
        }
    }

    # 子类
    public static class RoleUser extends AbstractBaseEntity {

        private String roleName;


        public String getRoleName() {
            return roleName;
        }

        public RoleUser setRoleName(String roleName) {
            this.roleName = roleName;
            return this;
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer("RoleUser{");
            sb.append("roleName='").append(roleName).append('\'');
            sb.append('}');
            sb.append(super.toString());
            return sb.toString();
        }
    }







    public static void main(String[] args) throws Exception{
        ObjectMapper objectMapper = new ObjectMapper();

        RoleUser roleUser = new RoleUser();
        roleUser.setRoleName("role");
        roleUser.setPassword("rolePwd");
        roleUser.setUserName("roleUserName");


        TokenUser tokenUser = new TokenUser();
        tokenUser.setToken("token");
        tokenUser.setPassword("tokenPassword");
        tokenUser.setUserName("tokenUserName");

        String roleStr = objectMapper.writeValueAsString(roleUser);
        String tokenStr = objectMapper.writeValueAsString(tokenUser);

        System.out