Как десериализовать JsonString, используя ObjectMapper с Generic Type класса - PullRequest
0 голосов
/ 12 октября 2018

Скажем, если у меня есть класс модели ResponseModel

@Setter // This one not working
public class ResponseModel<T> {

    private Class<T> responseClass;
    private String content; // JsonString

    public <T> T getContent() throws IOException { 
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(content, responseClass);
    }
}

Что я хочу сделать, так это то, что я хочу передать универсальный тип классу ResponseModel и когда я вызываю метод getContent(), ондолжен вернуть сопоставленный объект в соответствии с responseClass

Вот пример, который я хочу сделать

 // Color Pojo
    @Data
    public class Color {

        private String nameValue;
        private String hexValue;

    }

 // prepare mocked content
    final String content = "{\n" +
            "\"nameValue\":\"red\",\n" +
            "\"hexValue\":\"FFFFFF\"\n" +
            "}";

 // Declare ResponseModel Object
    ResponseModel<Color> response = new ResponseModel<>();
    response.setContent(content);
    response.getContent().getNameValue(); // should return red
    response.getContent().getHexValue(); // should return FFFFFF

Кто-нибудь знает, как это сделать?

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Вы можете написать интерфейс с JsonSubTypes для автоматической десериализации следующим образом:

@JsonIgnoreProperties(value = {"type"})
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Subclass1.class, name = "SUBCLASS1"),
        @JsonSubTypes.Type(value = Subclass2.class, name = "SUBCLASS2")
})
public interface DeserializableModelInterface {

}

и написать свой ResponseModel с этим конкретным объектом

public class ResponseModel<T extends AbstractDeserializer> {

    private T body;

    public ResponseModel(T body) {
        this.body = body;
    }

    public T getBody() {
        return body;
    }
}

Ваш body это конкретный объект, который вы можете получить во время выполнения без явного преобразования json

В вашем Subclass1, Subclass2 и т. д. у вас будет дополнительное свойство json, которое позволит Джексону де / сериализоватьавтоматически

    {
        "type": "SUBCLASS1"
        ... other properties
    }

Чтобы избежать ручного сопоставления для значения подкласса, вы можете использовать имя класса, например:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")
0 голосов
/ 12 октября 2018

Вы можете создать статический метод для десериализации объекта с универсальным типом

public class MyDeserializer {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static  <T> T convertValue(String content, Class<T> contentClass) throws IOException {
        Assert.notNull(content, "Content cannot be null");
        Assert.notNull(contentClass, "Content class must be specified");
        return objectMapper.readValue(content, contentClass);
    }
}

и проверить ваш метод:

Color color = MyDeserializer.convertValue("{" +
            "\"nameValue\":\"red\"," +
            "\"hexValue\":\"FFFFFF\"" + "}", Color.class);
assertEquals("red", color.getNameValue());
assertEquals("FFFFFF", color.getHexValue());

Таким образом, вы можете использовать десериализатор длялюбой класс во время выполнения.

ОБНОВЛЕНИЕ

Чтобы ваш пример работал, вам нужно удалить перед getContent совпадение с универсальным типом T из класса.

public  T getContent() throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    return  mapper.readValue(content, responseClass);
}

и для использования вашего метода:

responseModel.setContent("{" +
         "\"nameValue\":\"red\"," +
         "\"hexValue\":\"FFFFFF\"" + "}");
responseModel.setResponseClass(Color.class);

Во время выполнения универсальный тип заменяется на Object, поэтому вы должны указать ожидаемый класс.

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

...