• 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在基类上使用,比如:
     

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

    @JsonTypeName

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

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

    demo: 

    依赖:

    1. <dependency>
    2. <groupId>com.fasterxml.jackson.core</groupId>
    3. <artifactId>jackson-core</artifactId>
    4. <version>2.13.3</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>com.fasterxml.jackson.core</groupId>
    8. <artifactId>jackson-annotations</artifactId>
    9. <version>2.13.3</version>
    10. </dependency>
    11. <dependency>
    12. <groupId>com.fasterxml.jackson.core</groupId>
    13. <artifactId>jackson-databind</artifactId>
    14. <version>2.13.3</version>
    15. </dependency>
    1. package com.cjian.jackson;
    2. import com.fasterxml.jackson.annotation.JsonSubTypes;
    3. import com.fasterxml.jackson.annotation.JsonTypeInfo;
    4. import com.fasterxml.jackson.core.JsonProcessingException;
    5. import com.fasterxml.jackson.databind.ObjectMapper;
    6. /**
    7. * @Author: cjian
    8. * @Date: 2022/6/27 10:42
    9. * @Des:
    10. */
    11. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "partner", visible = true, defaultImpl = Man.class)
    12. @JsonSubTypes({
    13. @JsonSubTypes.Type(value = Man.class, name = "wife"),
    14. @JsonSubTypes.Type(value = Woman.class, name = "husband")
    15. })
    16. public abstract class Person {
    17. private String name;
    18. private int age;
    19. private String sex;
    20. private String partner;
    21. public String getName() {
    22. return name;
    23. }
    24. public void setName(String name) {
    25. this.name = name;
    26. }
    27. public int getAge() {
    28. return age;
    29. }
    30. public void setAge(int age) {
    31. this.age = age;
    32. }
    33. public String getSex() {
    34. return sex;
    35. }
    36. public void setSex(String sex) {
    37. this.sex = sex;
    38. }
    39. public String getPartner() {
    40. return partner;
    41. }
    42. public void setPartner(String partner) {
    43. this.partner = partner;
    44. }
    45. }

    两个子类:

    1. package com.cjian.jackson;
    2. import com.fasterxml.jackson.annotation.JsonTypeName;
    3. /**
    4. * @Author: cjian
    5. * @Date: 2022/6/27 10:44
    6. * @Des:
    7. */
    8. public class Man extends Person {
    9. private String wife;
    10. public String getWife() {
    11. return wife;
    12. }
    13. public void setWife(String wife) {
    14. this.wife = wife;
    15. }
    16. @Override
    17. public String toString() {
    18. return "Man{" +
    19. "wife='" + wife + '\'' +
    20. '}';
    21. }
    22. }
    1. package com.cjian.jackson;
    2. import com.fasterxml.jackson.annotation.JsonTypeName;
    3. /**
    4. * @Author: cjian
    5. * @Date: 2022/6/27 10:43
    6. * @Des:
    7. */
    8. public class Woman extends Person {
    9. private String husband;
    10. public String getHusband() {
    11. return husband;
    12. }
    13. public void setHusband(String husband) {
    14. this.husband = husband;
    15. }
    16. @Override
    17. public String toString() {
    18. return "Woman{" +
    19. "husband='" + husband + '\'' +
    20. '}';
    21. }
    22. }

    测试:

    1. package com.cjian.jackson;
    2. import com.fasterxml.jackson.core.JsonProcessingException;
    3. import com.fasterxml.jackson.databind.ObjectMapper;
    4. /**
    5. * @Author: cjian
    6. * @Date: 2022/6/29 10:30
    7. * @Des:
    8. */
    9. public class Test {
    10. public static void main(String[] args) throws JsonProcessingException {
    11. ObjectMapper objectMapper = new ObjectMapper();
    12. String jsonString1 = "{\"name\":\"cjian\",\"age\":28,\"sex\":\"男\",\"partner\":\"wife\",\"wife\":\"lili\"}";
    13. String jsonString2 = "{\"name\":\"lili\",\"age\":28,\"sex\":\"女\",\"partner\":\"husband\",\"husband\":\"cjian\"}";
    14. Person p1 = objectMapper.readValue(jsonString1, Man.class);
    15. Person p2 = objectMapper.readValue(jsonString2, Woman.class);
    16. System.out.println(p1);
    17. System.out.println(p2);
    18. }
    19. }

     

  • 相关阅读:
    Shopee、Lazada卖家不得不看的提升销量技巧,自养号测评打造权重
    Springboot物资发放管理系统
    MVC架构_Qt自己的MV架构
    Spring源码:Bean生命周期(三)
    2023.11.20使用flask做一个简单图片浏览器
    如何实现使用原生的Java API实现代理模式_java培训
    Android学习笔记 66. Android Studio 和 Hello World
    C++学习:this指针
    Android DocumentFile基本使用
    浅谈 RADIUS 认证协议的起源与未来展望
  • 原文地址:https://blog.csdn.net/cj_eryue/article/details/125508989