skip to Main Content

I am using Jackson to de-serialize this class

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

The problem is that datiPersonaFisica and datiDittaIndividuale are ambiguous

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

So it gives me the error

JSON parse error: Could not resolve subtype of [simple type, class
com.XXXX.cmp.cgw.webclient.bo.Dati]: Cannot deduce unique subtype of
com.xxxx.cmp.cgw.webclient.bo.Dati (2 candidates match); nested
exception is
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not
resolve subtype of [simple type, class
com.xxxx.cmp.cgw.webclient.bo.Dati]: Cannot deduce unique subtype of
com.xxxx.cmp.cgw.webclient.bo.Dati (2 candidates match)n at
[Source: (org.springframework.util.StreamUtils$NonClosingInputStream);
line: 12, column: 5] (through reference chain:
com.xxxx.cmp.cgw.webclient.dto.ClienteDTO["soggetto"]->com.xxxx.cmp.cgw.webclient.bo.Soggetto["anagrafica"])

I would like to auto-detect datiPersonaFisica if the specific fields of datiDittaIndividuale are missing. But I can’t find how in the documentation.

2

Answers


  1. Chosen as BEST ANSWER

    As of this answer, it seems not resolvable by deduction method. I have used an alternative strategy instead:

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

  2. The attributes in your DatiPersonaFisica class are a subset of the ones in DatiDittaIndividuale. If Jackson tries to deserialize a Json containing only the fields from DatiPersonaFisica, it has no way to tell which instance to construct, as the Json matches the fingerprint of both of your classes. See the issue #3577 on the official Jackson-databind repository.

    A Json constructed with only the fields from DatiPersonaFisica may either be an instance of DatiPersonaFisica, or an instance of DatiDittaIndividuale whose only serialized fields are the ones in common with DatiPersonaFisica; hence, the error message:

    Cannot deduce unique subtype of com.xxxx.cmp.cgw.webclient.bo.Dati (2 candidates match)

    In your case, since there is no way to tell which class is which with a DatiPersonaFisica‘s Json, an implementation with JsonTypeInfo.Id.NAME is better suited. Your classes could look like this:

    @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...
    }
    

    Here is a demo at OneCompiler

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search