Десериализовать JSON в полиморфные типы Spring boot

Я работаю над проектом электронной политики, где мне нужно сохранять разные типы политик. Для простоты я рассматриваю только два вида «LifeInsurance» и «AutoInsurance». Чего я хочу добиться, так это того, что если запрос JSON на создание политики содержит «тип»: «AUTO_INSURANCE», тогда запрос должен быть сопоставлен с AutoInsurance.class аналогично для LifeInsurance, но в настоящее время в весеннем загрузочном приложении запрос сопоставляется с родительским классом. Политика устраняет специальные поля запроса для автострахования/страхования жизни. Модель домена, которую я создал, приведена ниже.

@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;

}

Мой класс автострахования ниже.

@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;

}

Ниже приведен дочерний класс типа LifeInsurance.

@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;

}

Чтобы сохранить детали полиса, я отправляю запрос 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);
    }

Но когда я запускаю то же самое при загрузке Spring в постмэппинге RESTController, я получаю объект класса PArent вместо объекта дочернего класса.

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

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

Я могу получить JSON в виде строки, автоматически связать объект-сопоставитель и проанализировать вручную, но я хочу понять, является ли это известной проблемой, и сталкивался ли кто-нибудь с тем же с загрузкой Spring. Я искал решения по этому вопросу, но я нашел решение для десериализации полиморфных классов, но ничего не имело отношения к проблеме с загрузкой Spring.

У вас отсутствует аннотация @RequestBody в объекте запроса, поэтому ничего не будет десериализовано.

M. Deinum 10.04.2019 13:35

Большое спасибо :). Это решило проблему. Я просто проверял имя класса, но не проверял данные, отображаются они или нет. После добавления заработало

Raghav 10.04.2019 14:40

Вы можете добавить это как ответ, я приму это.

Raghav 10.04.2019 14:41
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
2 134
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем методе вы не аннотировали аргумент метода Policy с помощью @RequestBody. Это приводит к тому, что Spring создает только экземпляр Policy вместо использования Джексона для преобразования тела запроса.

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

Добавление @RequestBody приведет к тому, что Spring будет использовать Джексона для десериализации тела запроса, и при этом ваши аннотации/конфигурация будут эффективными.

Другие вопросы по теме