对于某些端点,我有以下 JSON 对象架构:
{ // Dog.java
"name": "Fido",
"age": 5,
"barkLoudness": 8,
"treatsToday": 2
}
{ // Cat.java
"name": "Fluffy",
"age": 2,
"color": "white",
}
{ // Fish.java
"name": "Professor",
"age": 1,
"blub": "blub"
}
所有模式共享
name
和 age
字段,但可以使用自己的属性扩展它。反序列化时,对象映射器也会知道其反序列化的类型,例如对 /dog
的 POST 调用 mapper.readValue(input, Dog.class)
。我正在努力解决的是如何定义类,这样我就不必重复所有的 name
和 age
字段:
abstract class Animal<T> { // abstract? interface? concrete?
private final String name;
private final int age;
@JsonUnwrapped
private final T info;
// unsure if Unwrapped works here
@JsonCreator
protected Animal(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonUnwrapped T info
) {
this.name = name;
this.age = age;
this.info = info;
}
// getters
}
public class Dog extends Animal<DogInfo> {
private final int barkLoudness;
private final int treatsToday;
// Don't want to have to repeat the name/age in concrete subtypes
// or the JsonProperty annotation
@JsonCreator
public Dog(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonProperty("barkLoudness") int barkLoudness,
@JsonProperty("treatsToday") int treatsToday
) {
super(name, age);
this.barkLoudness = barkLoudness;
this.treatsToday = treatsToday;
}
// getters
}
如果有帮助,我永远不会使用像
process(Animal<T> animal)
这样的方法,我将始终使用具体类型。我想让所有对象不可变,并且不要在所有对象之间重复 age
和 name
字段/定义。我有一个小小的偏好不使用 @JsonTypeInfo
注释,但如果这是解决方案,我就同意了。有没有办法创建类结构来实现这种“继承”?
您可以使用带有继承的 Jackson 注释来防止在所有对象之间重复年龄和名称字段/定义:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
abstract class Animal {
private final String name;
private final int age;
@JsonCreator
protected Animal(@JsonProperty("name") String name, @JsonProperty("age") int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
final class Dog extends Animal {
private final int barkLoudness;
private final int treatsToday;
@JsonCreator
public Dog(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonProperty("barkLoudness") int barkLoudness,
@JsonProperty("treatsToday") int treatsToday
) {
super(name, age);
this.barkLoudness = barkLoudness;
this.treatsToday = treatsToday;
}
public int getBarkLoudness() {
return barkLoudness;
}
public int getTreatsToday() {
return treatsToday;
}
}
final class Cat extends Animal {
private final String color;
@JsonCreator
public Cat(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonProperty("color") String color
) {
super(name, age);
this.color = color;
}
public String getColor() {
return color;
}
}
final class Fish extends Animal {
private final String blub;
@JsonCreator
public Fish(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonProperty("blub") String blub
) {
super(name, age);
this.blub = blub;
}
public String getBlub() {
return blub;
}
}
public class Main {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String dogJson = """
{
"name": "Fido",
"age": 5,
"barkLoudness": 8,
"treatsToday": 2
}
""";
Dog dog = mapper.readValue(dogJson, Dog.class);
System.out.println("Dog: " + dog.getName() + ", Age: " + dog.getAge() +
", Bark Loudness: " + dog.getBarkLoudness() +
", Treats Today: " + dog.getTreatsToday());
String catJson = """
{
"name": "Fluffy",
"age": 2,
"color": "white"
}
""";
Cat cat = mapper.readValue(catJson, Cat.class);
System.out.println("Cat: " + cat.getName() + ", Age: " + cat.getAge() +
", Color: " + cat.getColor());
String fishJson = """
{
"name": "Professor",
"age": 1,
"blub": "blub"
}
""";
Fish fish = mapper.readValue(fishJson, Fish.class);
System.out.println("Fish: " + fish.getName() + ", Age: " + fish.getAge() +
", Blub: " + fish.getBlub());
}
}
输出:
Dog: Fido, Age: 5, Bark Loudness: 8, Treats Today: 2
Cat: Fluffy, Age: 2, Color: white
Fish: Professor, Age: 1, Blub: blub