Jackson framework handles polymorphic classes

       

 Sometimes, the specific objects stored in a table may be different. For example, in the Person table, I store man and woman in it. Except for common attributes such as name, age, gender, etc., there may be some attributes that are different. For man, woman and There are different other business processes, etc. At this time, we all use the same interface for adding or modifying. If a specific object is passed, various judgment logics cannot be avoided. The code is too redundant, so how to directly pass the top-level one What about the abstract class (Person)? This involves a polymorphic processing~ This is the Jackson framework, the protagonist of this article

Jackson allows configuration of polymorphic type processing. When deserializing a session, the object matched by JSON data may have multiple subtypes. In order to correctly read the type of the object, we need to add some type information. This can be achieved through the following annotations:

@JsonTypeInfo

Acts on classes/interfaces and is used to enable polymorphic type processing, valid for both base classes/interfaces and subclasses/implementation classes

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


Attribute introduction:

  • use : Define which type identifier to use, it has the following optional values:
    • JsonTypeInfo.Id.CLASS: use the fully qualified class name for identification
    • JsonTypeInfo.Id.MINIMAL_CLASS: If the base class and subclass are in the same package class, use the class name (ignoring the package name) as the identification code
    • JsonTypeInfo.Id.NAME: a logically assigned name
    • JsonTypeInfo.Id.CUSTOM: Custom identification code, by @JsonTypeIdResolvercorresponding, explained later
    • JsonTypeInfo.Id.NONE: No identifier is used
  • include (optional): Specify how the identifier is included, it has the following optional values:
    • JsonTypeInfo.As.PROPERTY: As a sibling property of data (default)
    • JsonTypeInfo.As.EXISTING_PROPERTY: As an existing property in POJO
    • JsonTypeInfo.As.EXTERNAL_PROPERTY: as an extended property
    • JsonTypeInfo.As.WRAPPER_OBJECT: as a wrapper object
    • JsonTypeInfo.As.WRAPPER_ARRAY: as a wrapped array
  • property (optional): The name of the property specifying the identifier.
    This property is only available if:
    • useis JsonTypeInfo.Id.CLASS(the default is if the property is not specified @class), JsonTypeInfo.Id.MINIMAL_CLASS(the default is if the property is not specified @c), JsonTypeInfo.Id.NAME(the default is if the property is not specified @type),
    • includeOnly effective when JsonTypeInfo.As.PROPERTY, JsonTypeInfo.As.EXISTING_PROPERTY,JsonTypeInfo.As.EXTERNAL_PROPERTY
  • defaultImpl(Optional): If the type identifier does not exist or is invalid, you can use this attribute to specify the default type used when deserializing
  • visible (optional, default to false): Whether
    the visible attribute defines whether the value of the type identifier will become part of the deserializer through the JSON stream, the default is false, that is, jackson will process and delete it from the JSON content The type identifier is then passed to the JsonDeserializer.

@JsonSubTypes

Acts on classes/interfaces to list the subclasses of a given class. It will only be used when the subclass type cannot be detected. It is usually used with @JsonTypeInfo on the base class, such as:
 

@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

Acting on subclasses, it is used to specify the value of the type identifier for polymorphic subclasses. With this annotation, @JsonSubTypes can be used instead of @JsonSubTypes,
for example:

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

demo: 

rely:

<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;
    }
}

Two subclasses:

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 + '\'' +
                '}';
    }
}

test:

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);
    }
}

 

Guess you like

Origin blog.csdn.net/cj_eryue/article/details/125508989