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 identificationJsonTypeInfo.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 codeJsonTypeInfo.Id.NAME
: a logically assigned nameJsonTypeInfo.Id.CUSTOM
: Custom identification code, by@JsonTypeIdResolver
corresponding, explained laterJsonTypeInfo.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:use
isJsonTypeInfo.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
),include
Only effective whenJsonTypeInfo.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);
}
}