将JSON反序列化为多态类型Spring Boot

时间:2019-04-10 11:23:15

标签: java json spring-boot

我正在从事一个电子政策项目,需要保存各种类型的政策。为简单起见,我只考虑“人寿保险”和“自动保险”两种类型。我要实现的是,如果创建策略的JSON请求包含“ type”:“ AUTO_INSURANCE”,则该请求也应映射到AutoInsurance.class,同样适用于LifeInsurance,但当前在Spring Boot应用中,该请求已映射到父类Policy汽车/人寿保险的特定请求字段。我创建的域模型如下。

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@NoArgsConstructor
@Getter
@Setter
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = 
JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ @Type(value = AutoInsurance.class, name = "AUTO_INSURANCE"),
    @Type(value = LifeInsurance.class) })
public class Policy {

    @Id
    @GeneratedValue
    private Long id;
    private String policyNumber;
    @Enumerated(EnumType.STRING)
    private PolicyType policyType;
    private String name;

}

我的AutoInsurance课程在下面。

@Entity
@NoArgsConstructor
@Getter
@Setter
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonTypeName(value = "AUTO_INSURANCE")
public class AutoInsurance extends Policy {

    @Id
    @GeneratedValue
    private Long id;
    private String vehicleNumber;
    private String model;
    private String vehicleType;
    private String vehicleName;

}

下面是人寿保险类型的子班

@Entity
@NoArgsConstructor
@Getter
@Setter
@JsonTypeName(value = "LIFE_INSURANCE")
public class LifeInsurance extends Policy {

    @OneToMany(mappedBy = "policy")
    private List<Dependents> dependents;
    private String medicalIssues;
    private String medication;
    private String treatments;

}

要保存保单详细信息,我正在从UI发送带有“ type”属性的JSON请求,该属性指示请求中的保险类型。

当我运行以下测试方法时,JSON请求将根据需要映射到正确的子类。

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException  {
        ObjectMapper map = new ObjectMapper();
        String s = "{\"id\": 1,\"policyNumber\": \"Aut-123\",\"type\": \"AUTO_INSURANCE\",\"policyType\": \"AUTO_INSURANCE\",\"name\": null,\"address\": null,\"contact\": null,\"agentNumber\": null,\"agentName\": null,\"issuedOn\": null,\"startDate\": null,\"endDate\": null,\"vehicleNumber\": \"HR\",\"model\": null,\"vehicleType\": \"SUV\",\"vehicleName\": null}";
        Policy p = map.readValue(s, Policy.class);
        System.out.println(p.getClass());
        //SpringApplication.run(EPolicyApplication.class, args);
    }

但是当我在RESTController后映射中的Spring Boot中运行相同的代码时,我得到的是PArent类对象而不是子类对象。

@RestController
@RequestMapping("/policy")
public class PolicyController {

    @PostMapping
    public void savePolicy(Policy policy) {
        System.out.println(policy.getClass());
    }
}

我可以将JSON作为字符串,自动装配对象映射器并手动进行解析,但我想了解它是否是已知问题,以及其他人在Spring Boot中是否也遇到过同样的问题。我已经在此寻找解决方案,但得到的是反序列化为多态类的解决方案,但与Spring boot问题无关。

1 个答案:

答案 0 :(得分:0)

在您的方法中,您没有用Policy注释@RequestBody方法参数。这导致Spring仅创建Policy的实例,而不是使用Jackson转换请求正文。

@PostMapping
public void savePolicy(@RequestBody Policy policy) {
    System.out.println(policy.getClass());
}

添加@RequestBody将使Spring使用Jackson来反序列化请求正文,并且注释/配置将有效。