多个对象之间的 JSON 模式共享字段

问题描述 投票:0回答:1

对于某些端点,我有以下 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
注释,但如果这是解决方案,我就同意了。有没有办法创建类结构来实现这种“继承”?

java json inheritance jackson
1个回答
0
投票

您可以使用带有继承的 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
© www.soinside.com 2019 - 2024. All rights reserved.