如何使用带有类通用类型的ObjectMapper反序列化JsonString

时间:2018-10-12 09:21:22

标签: java spring spring-boot jackson objectmapper

假设我有一个模型课程fo:region-body

Document document = new Document();

我想做的是将通用类型传递给类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); } } 时,它应该根据responseClass返回映射的对象

这是我想做的一个例子

ResponseModel

有人知道该怎么做吗?

2 个答案:

答案 0 :(得分:1)

您可以使用静态方法反序列化具有通用类型的对象

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的类型。

答案 1 :(得分:0)

您可以使用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

在您的Subclass1Subclass2等中,您将拥有一个附加的json属性,该属性将允许jackson自动进行反序列化/序列化

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

要避免手动映射子类值,可以使用类名,例如:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "class")