Модифицированная десериализация интерфейса

#java #json #jackson #retrofit #jackson-databind

#java #json #джексон #модернизация #джексон-привязка данных

Вопрос:

У меня есть объект ответа, который всегда включает объект ответа как свойство и различные типы значений, поэтому у меня есть интерфейс в классе как поле, чтобы он обеспечивал правильную реализацию на основе некоторого уникального идентификатора значения.

 Could not execute the callcom.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.opngo.nowos.nowos.api.response.DataResponse]: missing type id property 'operation' (for POJO property 'response')
 at [Source: (okhttp3.ResponseBody$BomAwareReader); line: 1, column: 180] (through reference chain: com.opngo.nowos.nowos.NowOSResponse["response"])
 

Вот мой интерфейс

 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "operation")
@JsonSubTypes({@JsonSubTypes.Type(value = AuthResponse.class, name = "account_auth")})
public interface IResponse {
    ///
}
 

Вот один из объектов ответа, который реализует интерфейс, упомянутый выше

 @RequiredArgsConstructor
public class AuthResponse implements IResponse {

    @JsonProperty
    private final String accountID;
    @JsonProperty
    private final String authToken;
    @JsonProperty
    private final String language;
}
 

Вот основной ответ, который имеет этот интерфейс, который должен привести к правильному объекту ответа

     public class NowOSResponse {

    @JsonProperty
    private final String operation;
    @JsonProperty
    private final String version;
    @JsonProperty
    private final IResponse response;
    @JsonProperty
    private final String status;

}
 

Похоже, что он не просматривает родительский элемент и ищет поле operation в authResponse, которое, конечно, пустое, поскольку поле operation всегда присутствует в родительском элементе, и у этого родительского элемента есть response -> authResponse -> CreateAccResponse и так далее

Ответ №1:

я хотел бы опубликовать решение, которое, надеюсь, поможет вам.

Если у вас есть объект внутри объекта, который всегда возвращает разные свойства, вы можете использовать следующее :

1) Создайте абстрактный класс, например MainResponse, этот ответ будет содержать статус и операцию, поскольку эти свойства являются постоянными

 public abstract class MainResponse {

    @JsonProperty
    private String version;
    
    public abstract IResponse getResponse(); // so we declaring it abstract so that all the childrens have to override it in order to return specific interface realisation

}
 

Теперь нам нужно создать конкретное тело ответа, которое должно быть возвращено на основе вызова api.

 @Getter
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthResponse implements IResponse {

    @JsonProperty
    private String accountID;
    @JsonProperty
    private String authToken;

}
 

Теперь, поскольку json будет ожидать свойство response json, мы должны создать дополнительный класс, который расширит абстрактный класс, что означает, что у нас будет GetResponse, которому требуется IResponse в качестве возврата, и, следовательно, мы должны реализовать этот интерфейс в authResponse , мы можем просто заключить authResponse как объект композиции в новом, скажем, классе NewResponse иверните его.

 @Getter
public class NewResponse extends MainResponse {

    @JsonProperty
    private AuthResponse response;
}