Jackson根据Cat实例的字段类型(多态)将2种不同的序列化器序列化为Animal和Cat

时间:2018-03-09 12:29:15

标签: 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 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}}

我无法反序列化,因为AnimalDeserializer需要知道能够构建它的动物类型。

理想情况下,它会将FieldSerializer用于字段Animal catB,我会得到:

{"catA" : {"name":"Felix", "livesLeft":9},
"catB" : {"animalType":"Cat", "name":"Madonna", "livesLeft":3}}

可以反序列化。

变通方法的想法:在序列化期间是否有办法确定字段类型(而不仅仅是实例类型)?因此对于将返回Animal catB = new Cat("Madonna", 3)的字段AnimalCat

2 个答案:

答案 0 :(得分:1)

由于您说您不想注释字段,因此可以定义一个ContextualSerializer,它根据字段类型返回一个序列化程序。然后,您可以为每个Animal子类型而不是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
    }
}

然后只需将其插入:

module.addSerializer(Animal.class, new AnimalSerializer());
// Delegates to AnimalSerializer if the field type is Animal instead of Cat
module.addSerializer(Cat.class, new CatSerializer()); 

答案 1 :(得分:1)

我希望这个解决方案适合您,或者对此进行任何适当的调整。您期望的行为是forType(Animal.class)的使用。

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"}