Джексон использует десериализацию на основе вывода, когда поля отсутствуют

Я использую Джексона для десериализации этого класса

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
        @JsonSubTypes.Type(value = DatiSocieta.class, name = "datiSocieta"),
        @JsonSubTypes.Type(value = DatiPersonaFisica.class, name = "datiPersonaFisica") ,
        @JsonSubTypes.Type(value = DatiDittaIndividuale.class, name = "datiDittaIndividuale") }
)
public interface Dati {
}

Проблема в том, что datiPersonaFisica и datiDittaIndividuale неоднозначны.

@Data
public
class DatiPersonaFisica implements Dati {
    private String codiceFiscale;
    private String sesso;
    private String nome;
    private String cognome;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date dataNascita;
    private String luogoNascita;
    private String provinciaNascita;
    private String nazioneNascita;
}

@Data
public
class DatiDittaIndividuale implements Dati {
    private String denominazione;
    private String codiceFiscale;
    private String sesso;
    private String nome;
    private String cognome;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date dataNascita;
    private String luogoNascita;
    private String provinciaNascita;
    private String nazioneNascita;
    private String numeroRea;
    private String provinciaCCIA;
    private String partitaIVA;
}

Поэтому это дает мне ошибку

Ошибка анализа JSON: не удалось разрешить подтип [простой тип, класс com.XXXX.cmp.cgw.webclient.bo.Dati]: невозможно определить уникальный подтип com.xxxx.cmp.cgw.webclient.bo.Dati (соответствуют 2 кандидата); вложенный исключением является com.fasterxml.jackson.databind.exc.InvalidTypeIdException: не удалось разрешить подтип [простой тип, класс com.xxxx.cmp.cgw.webclient.bo.Dati]: невозможно определить уникальный подтип com.xxxx.cmp.cgw.webclient.bo.Dati (соответствуют 2 кандидата)\n в [Источник: (org.springframework.util.StreamUtils$NonClosingInputStream); строка: 12, столбец: 5] (через цепочку ссылок: com.xxxx.cmp.cgw.webclient.dto.ClienteDTO["soggetto"]->com.xxxx.cmp.cgw.webclient.bo.Soggetto["anagrafica"])

Я хотел бы автоматически определить datiPersonaFisica, если определенные поля datiDittaIndividuale отсутствуют. Но я не могу найти как это сделать в документации.

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

Ответы 2

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

Атрибуты вашего класса DatiPersonaFisica являются подмножеством атрибутов класса DatiDittaIndividuale. Если Джексон попытается десериализовать Json, содержащий только поля из DatiPersonaFisica, он не сможет определить, какой экземпляр создавать, поскольку Json соответствует отпечаткам обоих ваших классов. См. выпуск #3577 в официальном репозитории Jackson-databind.

Json, созданный только с полями из DatiPersonaFisica, может быть либо экземпляром DatiPersonaFisica, либо экземпляром DatiDittaIndividuale, чьи единственные сериализованные поля являются общими с DatiPersonaFisica; следовательно, сообщение об ошибке:

Невозможно определить уникальный подтип com.xxxx.cmp.cgw.webclient.bo.Dati (соответствуют 2 кандидата)

В вашем случае, поскольку невозможно определить, какой класс с помощью Json DatiPersonaFisica, вы можете либо использовать реализацию с JsonTypeInfo.As.PROPERTY, либо JsonTypeInfo.As.EXTERNAL_PROPERTY, как предложено в теме проблем.

Решение с JsonTypeInfo.As.PROPERTY

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "datiType"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = DatiSocieta.class, name = "datiSocieta"),
        @JsonSubTypes.Type(value = DatiPersonaFisica.class, name = "datiPersonaFisica"),
        @JsonSubTypes.Type(value = DatiDittaIndividuale.class, name = "datiDittaIndividuale")
})
public interface Dati {
}

@Data
public class DatiSocieta implements Dati {
    // fields...
}

@Data
public class DatiPersonaFisica implements Dati {
    // fields...
}

@Data
public class DatiDittaIndividuale implements Dati {
    // fields...
}

Вот демо-версия OneCompiler 1

Решение с JsonTypeInfo.As.EXTERNAL_PROPERTY

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
        property = "type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = DatiPersonaFisica.class, name = "DatiPersonaFisica"),
        @JsonSubTypes.Type(value = DatiDittaIndividuale.class, name = "DatiDittaIndividuale")
})
public class Company {
    protected Dati dati;
    
    //constructors
    
    //getters and setters
}

public class Dati {
    private String nome;
    private String cognome;

    //constructors

    //getters and setters
}

public class DatiPersonaFisica extends Company {

    //constructors

    //getters and setters
}

public class DatiDittaIndividuale extends Company {
    private String denominazione;

    //constructors

    //getters and setters
}

Вот ссылка на вторую реализацию в OneCompiler 2

Я предпочитаю не использовать этот метод и вместо этого использовать дедуцирование.

Lore 23.05.2024 21:18

@Lore Deduction не может работать в вашем случае. DatiPersonaFisica всегда будет генерировать неоднозначный JSON, который соответствует отпечатку обоих ваших классов. Вот ссылка на проблему № 3577 официального репозитория Jackson-Databind, где пользователь проиллюстрировал вашу ту же проблему. Предлагаемые решения заключались в использовании JsonTypeInfo.As.PROPERTY (как в ответе) или JsonTypeInfo.As.EXTERNAL_PROPERTY. github.com/FasterXML/jackson-databind/issues/…

dani-vta 23.05.2024 21:47

Что касается этого ответа, он кажется неразрешимым методом дедукции. Вместо этого я использовал альтернативную стратегию:

@Data
public class Soggetto {
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "tipo")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = DatiSocieta.class, name = "SOCIETA"),
            @JsonSubTypes.Type(value = DatiPersonaFisica.class, name = "PERSONA_FISICA") ,
            @JsonSubTypes.Type(value = DatiDittaIndividuale.class, name = "DITTA_INDIVIDUALE") }
    )
    private Dati anagrafica;
    private Residenza residenza;
    private String tipo;
}

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