Десериализатор JSON с универсальным типом с использованием TypeReference - PullRequest
0 голосов
/ 12 декабря 2018

Я пытаюсь обобщить этот метод:

public EventStream<Greeting> deserialize(String value){
    ObjectMapper mapper = new ObjectMapper();

    EventStream<Greeting> data = null;
    try {
        data = new ObjectMapper().readValue(value, new TypeReference<EventStream<Greeting>>() {});
    } catch (IOException e) {
        e.printStackTrace();
    }
    return data;
}

, где EventStream:

public class EventStream<T> {

    private EventHeaders headers;

    @JsonDeserialize
    private T payload;
}

То, что я хотел бы получить, это заменить конкретное приветствие объекта на общее, в методе десериализации.

Я пытался с этим:

public <T> EventStream<T> deserialize(String value){
    ObjectMapper mapper = new ObjectMapper();

    EventStream<T> data = null;
    try {
        data = new ObjectMapper().readValue(value, new TypeReference<EventStream<T>>() {});
    } catch (IOException e) {
        e.printStackTrace();
    }
    return data;
}

Но полезная нагрузка внутри результата EventStream десериализована как LinkedHashMap.Кажется, что TypeReference проигнорировал универсальный тип.Любая идея?Спасибо

1 Ответ

0 голосов
/ 13 декабря 2018

То, с чем вы столкнулись здесь, является распространенной проблемой, вызванной чем-то, называемым стиранием типов, то есть способом, который реализует java.

Стирание типов может быть объяснено как процесс применения ограничений типов только во время компиляции иотбрасывание информации о типе элемента во время выполнения.[1]

Таким образом, в то время, когда вы пытаетесь десериализовать ваш объект, тип T не известен, и он просто обрабатывается как Object, а результатом десериализации по умолчанию будет Map (LinkedHashMap, если быть точным).

Вы можете сделать свой метод универсальным, передав свой targetClass в качестве дополнительного аргумента к вызову функции, например так:

public <T> EventStream<T> deserialize(String value, Class<T> targetClass)

Затем вы используете TypeFactory изваш маппер для создания типа этого targetClass

JavaType type = mapper.getTypeFactory().constructParametricType(EventStream.class, targetClass);

, который вы можете передать методу readValue:

data = mapper.readValue(value, type);

Полный код:

public <T> EventStream<T> deserialize(String value, Class<T> targetClass){
    ObjectMapper mapper = new ObjectMapper();
    JavaType type = mapper.getTypeFactory()
        .constructParametricType(EventStream.class, targetClass);
    try {
        return mapper.readValue(value, type);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

[1] https://www.baeldung.com/java-type-erasure

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...