如何在Jackson中嵌入实体继承字段?

时间:2017-10-26 09:08:34

标签: java json spring spring-boot jackson

如果我有两个扩展抽象类的类:

public abstract class Vehicle {
    private String model;
}

public class Car extends Vehicle {
    private int seatingCapacity;
    private double topSpeed;
}

public class Truck extends Vehicle {
    private double payloadCapacity;
}

我想使用jackson(和spring-boot)在JSON中序列化数据。 默认情况下,JSON如下所示:

[
    {"model": "vw", "type": "car", "seatingCapacity": 5, ...},
    {"model": "volvo", "type": "truck", "payloadCapacity": 10, ...},
    ...
]

但是对于API,我需要将每个子类的特定字段包含在类类型中。

[
    {
     "model": "vw", 
     "type": "car", 
     "car": {"seatingCapacity": 5, ...}
    },
    {
     "model": "volvo", 
     "type": "truck", 
     "truck": {"payloadCapacity": 10, ...}
    },
    ...
]

2 个答案:

答案 0 :(得分:0)

这是一个奇怪的案例,因为您的默认JSON实际上代表了您定义它们的车辆。我想说最简单的方法是,如果这些对象仅用于表示发送以将类修改为类似的响应:

public class Car extends Vehicle {
   CarProperties car=new CarProperties();

   class CarProperties {
      private int seatingCapacity;
      private double topSpeed;
   }
}

这可能不是很酷,但它代表你想要的json。此外,如果您没有在Vehicle类中拥有代码但只是定义属性,则可以使用带有一个getModel()方法的接口替换它。

另一种解决方案是编写自定义的Jackson序列化程序,但它会使代码更加复杂,并将对象与它结合起来。或者您当然可以使用一些JsonObject类从这些属性生成自己的json并手动添加属性。

答案 1 :(得分:0)

如果有必要,可以使用Jackson创建自定义反序列化器。如果你有可能创建一个与卡车和汽车相同的结构,我会首先尝试,因为它更容易实现。但是否则你可以创建类似的东西:

public class VehicleDeserializer extends JsonDeserializer<Vehicle> { 

    @Override
    public Vehicle deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);

        String vehicleType = node.get("type").asText();

        if (vehicleType.equals("car")) {
            // Values should be loaded through node
            return new Car();
        }

        if (vehicleType.equals("truck")) {
            // Values should be loaded through node
            return new Truck();
        }

        // Return default or exception if not recognized
    }
}

ObjectMapper必须更新:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Vehicle.class, new VehicleDeserializer());
mapper.registerModule(module);