Json Jackson使用2个不同的序列化程序序列化Animal和Cat,具体取决于Cat实例的字段类型(多态性)

Json Jackson使用2个不同的序列化程序序列化Animal和Cat,具体取决于Cat实例的字段类型(多态性),json,jackson,jackson2,Json,Jackson,Jackson2,我有一类动物和一类猫,它们扩展了: class Animal { protected String name; ... } class Cat extends Animal { protected int livesLeft; ... } 每个都有一个单独的JsonSerializer: module.addSerializer(Cat.class, new CatSerializer()); module.addSerializer(Animal.class, new Ani

我有一类动物和一类猫,它们扩展了:

class Animal {
  protected String name;
  ...
}
class Cat extends Animal {
  protected int livesLeft;
  ...
}
每个都有一个单独的
JsonSerializer

module.addSerializer(Cat.class, new CatSerializer());
module.addSerializer(Animal.class, new AnimalSerializer());
现在我想序列化此类的一个实例:

class Foo {
   Cat catA = new Cat("Felix", 9);
   Animal catB = new Cat("Madonna", 3);
}
但当我这样做时,两个字段都使用
CatSerializer
,因此我得到

{"catA" : {"name":"Felix", "livesLeft":9},
"catB" : {"name":"Madonna", "livesLeft":3}}
这是我不能反序列化的,因为动物生物学家需要知道动物的类型才能构建它

理想情况下,它会在野外使用动物序列化器
动物catB
,我会得到:

{"catA" : {"name":"Felix", "livesLeft":9},
"catB" : {"animalType":"Cat", "name":"Madonna", "livesLeft":3}}
可以反序列化


解决方案:在序列化过程中有没有办法确定字段类型(不仅仅是实例类型)?因此对于field
Animal catB=new Cat(“Madonna”,3)
,它将返回
Animal
,而不是
Cat
,因为您说不想注释字段,可以根据字段类型定义返回序列化程序的。然后,您可以为每个
动物
子类型而不是
JsonSerializer
扩展它。例如:

abstract class ByFieldTypeSerializer<T> extends JsonSerializer<T> implements ContextualSerializer {
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        // getType will return the field type i.e. Animal for catB
        // SerializerProvider argument knows about all serializers by type
        return prov.findValueSerializer(property.getType());
    }
}

class CatSerializer extends ByFieldTypeSerializer<Cat> {
    @Override
    public void serialize(Cat value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        // serialize a Cat
    }
}

我希望这个解决方案对您有效,或者任何适当的调整。使用
forType(Animal.class)
可以产生您期望的行为

生成的输出如下所示:

{"name":"mycat","livesLeft":3}
{"name":"mycat","animalType":"Cat"}

我有一个复杂的问题:Animal和Cat是第三方类,我不能直接修改它们,只能为它们编写序列化程序/反序列化程序。但是有了mixin,这个解决方案可能会奏效,谢谢。太好了。工作就像一个符咒:)
public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    Cat cat = new Cat();
    cat.livesLeft=3;
    cat.name="mycat";
    System.out.println(objectMapper.writer().writeValueAsString(cat));

    Animal animal = cat;
    System.out.println(objectMapper.writer().forType(Animal.class).writeValueAsString(animal));
}

@Data
static abstract class Animal {
    protected String name;

    public String getAnimalType(){
        return this.getClass().getSimpleName();
    }
}

@JsonIgnoreProperties("animalType")
@Data
static class Cat extends Animal {
    protected int livesLeft;
}
{"name":"mycat","livesLeft":3}
{"name":"mycat","animalType":"Cat"}