使用JsonTypeInfo从Jackson序列化中删除基类名称

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用JsonTypeInfo从Jackson序列化中删除基类名称相关的知识,希望对你有一定的参考价值。

这是我的继承设置:

抽象类Animal

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include =JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class)})

public abstract class Animal {
}

具体类狗:

public class Dog extends Animal {

  private final String breed;

  public Dog(String breed) {
      this.breed = breed;
  }

  public String getBreed() {
      return breed;
  }
}

Animal的简单包装类:

public class AnimalWrapper {

  private final Animal animal;

  public AnimalWrapper(Animal animal) {
      this.animal = animal;
  }

  public Animal getAnimal() {
      return animal;
  }
}

序列化代码:

ObjectMapper objectMapper = new ObjectMapper();
Animal myDog = new Dog("english shepherd");
AnimalWrapper animalWrapper = new AnimalWrapper(myDog);
String dogJson = objectMapper.writeValueAsString(animalWrapper);

dogJson的价值是:

{"animal":{"Dog":{"breed":"english shepherd"}}}

我想要的是没有基类名称(动物)的JSON:

{"Dog":{"breed":"english shepherd"}}

我尝试在@JsonUnwrappedanimal周围使用AnimalWrapper,在这种情况下,animalDog都被淘汰了(这不是我想要的):

{"breed":"english shepherd"}

有没有办法实现我想要的?

答案

你需要为你的JsonSerializer定制AnimalWrapper才能跳过这一点。

public class ResponseSerializer extends JsonSerializer<AnimalWrapper> {


    @Override
    public void serialize(AnimalWrapper value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        final Object animal = value.getAnimal();
        Class<?> responseClass = animal.getClass();
        JavaType responseJavaType = serializers.constructType(responseClass);
        gen.writeStartObject();
        gen.writeFieldName(serializers.findTypeSerializer(responseJavaType).getTypeIdResolver().idFromValue(animal));
        serializers.findValueSerializer(responseClass).serialize(animal, gen, serializers);
        /* Here you must manually serialize other properties */
        /* Like gen.writeStringField("property", value.getProperty()); */
        gen.writeEndObject();
    }
}

使用AnimalWrapper注释注释您的@JsonSerialize并指定自定义序列化程序。

@JsonSerialize(using = ResponseSerializer.class)
public class AnimalWrapper<T> {

  private final T animal;

  public AnimalWrapper(T animal) {
      this.animal = animal;
  }

  public T getAnimal() {
      return animal;
  }
}

快速测试:

ObjectMapper objectMapper = new ObjectMapper();
Animal myDog = new Dog("english shepherd");
AnimalWrapper animalWrapper = new AnimalWrapper(myDog);
String dogJson = objectMapper.writeValueAsString(animalWrapper);
System.out.println(dogJson);

输出:

{“dog”:{“品种”:“英国牧羊犬”}}

另一答案

我想你已经遇到了杰克逊的一个弱点,详见此处......

Unwrapped annotation issue

我建议的解决方案是这里描述的自定义序列化器...

Jackson Custom Serializer

以上是关于使用JsonTypeInfo从Jackson序列化中删除基类名称的主要内容,如果未能解决你的问题,请参考以下文章

Jackson 反序列化意外令牌(END_OBJECT),

JSONTypeInfo 不忽略继承映射中的属性

JSON Jackson - 使用自定义序列化程序序列化多态类时的异常

使用Jackson As.External_Property和Collection

Jackson 的 @JsonTypeInfo(use = Id.CUSTOM, include = As.PROPERTY, property = "type") 读取 JSON

Spring Boot 忽略 Rest Controller 中的 Jackson 注释