Как десериализовать типы, которые наследуют общий базовый класс - с помощью Gson? - PullRequest
0 голосов
/ 24 января 2019

У меня есть следующая иерархия:

ОТВЕТ

public class Response implements Serializable {

    @SerializedName("message")
    @Expose
    private List<Message> messages;

    public List<Message> getMessages() {
        return messages;
    }

    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }

}

СООБЩЕНИЕ

public class Message implements Serializable {

        @SerializedName("type")
        @Expose
        @MessageType
        private int type;

        @SerializedName("position")
        @Expose
        @MessagePosition
        private String position;

        public int getType() {
            return type;
        }

        public String getPosition() {
            return position;
        }

        public void setType(@MessageType int type) {
            this.type = type;
        }

        public void setPosition(@MessagePosition String position) {
            this.position = position;
        }

}

ТЕКСТ -> СООБЩЕНИЕ

public class TextMessage extends Message {

@SerializedName("text")
@Expose
private String text;

public String getText() {
    return text;
}

public void setText(String text) {
    this.text = text;
}

}

ИЗОБРАЖЕНИЕ -> СООБЩЕНИЕ

public class ImageMessage extends Message {

    @SerializedName("attachment")
    @Expose
    private Attachment attachment;

    public Attachment getAttachment() {
        return attachment;
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

}

Попытка десериализации сообщения таким способом с GSonприводит (естественно) к пустым полям в text или attachment полях. Я хотел бы иметь наилучшую десериализацию, которая на основе ответа будет выбирать во время выполнения, какой тип сообщения (т. Е. Текст или изображение) соответствует большинству полей, которые должны быть выполнены.

Пока чтоединственные мысли, которые у меня были:

1 - Использовать @JsonAdapter -> Не работало

2 - Создать другую иерархическую структуру для указания классов во время компиляции, например:

---- Response
   |
    - TextResponse -> List<TextMessage>
   |
    - ImageResponse -> List<ImageMessage>

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

Кто-нибудь знает способ решения этой проблемы?Какие-либо рамки или концепции, которые могут быть применены?

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Может быть, вы могли бы использовать дополнения Gson RunTimeTypeAdapterFactory.Проверьте этот пример:

RuntimeTypeAdapterFactory<Message> factory = RuntimeTypeAdapterFactory
    .of(Message.class, "type") // actually type is the default field to determine
                               // the sub class so not needed to set here
                               // but set just to point that it is used
    // assuming value 1 in field "int type" identifies TextMessage
    .registerSubtype(TextMessage.class, "1")
    // and assuming int 2 identifies ImageMessage
    .registerSubtype(ImageMessage.class, "2");

Затем используйте GsonBuilder.registerTypeAdapterfactory(factory), чтобы использовать это.

Это просто не найдено в базовой библиотеке Gson .Вам нужно получить его здесь .Вы также можете найти какой-нибудь Maven / Gradle dep из глобального репо, который кто-то сделал, но, возможно, проще всего просто скопировать этот файл.

Позволяет использовать более поздние хаки, если вам нужно изменить его поведение.

0 голосов
/ 24 января 2019

Я реализовал это с GodClass, в котором есть все поля типов сообщений.

, но вы не используете эти классы POJO как DTO (объект передачи данных) в вашем приложении.

Json - это протокол, который не поддерживается Inheritance и т. Д.

В том же сценарии я реализовал это наследование и иерархию для DTO.

PS: DTO в моем ответе - Модели, которые мы передаемнапример, в Adapter или Activity и т. д.

...