java中将json数组字符串转换为list的泛型方法

rn0zuynd  于 2021-07-11  发布在  Java
关注(0)|答案(2)|浏览(410)

我一直在尝试为我的项目创建一个实用程序,让您 List<DesiredTypeClass> 来自相同的json字符串。
以下是我目前的执行情况:

public static <T> List<?> stringToClassList(String data, Class<T> convertType, ObjectMapper mapper) {
    if (!StringUtils.isBlank(data)) {
        try {
            if (mapper.readTree(data).size() != 0) {
                return Arrays.asList(mapper.convertValue(mapper.readTree(data), Array.newInstance(convertType, 0).getClass()));
            }
        }
        catch (JsonProcessingException processingException) {
            LOGGER.error("Error coverting String to Json, Error: {}", processingException);
            throw new UnrecoverableRequestException(processingException);
        }
     }
     return new ArrayList<>();
}

要调用这个方法,您应该有:arraystring、一个classtype(例如:use mydto.class to get list)和一个objectmapper示例;
围绕这一点编写一个测试用例,我在结果中发现了和额外的数组大括号:

java.lang.AssertionError: 
Expected :[{"startDate":"2020-12-01","endDate":"2020-12-02"},{"startDate":"2020-12-10","endDate":"2020-12-11"}]
Actual   :[[{"startDate":"2020-12-01","endDate":"2020-12-02"},{"startDate":"2020-12-10","endDate":"2020-12-11"}]]

以下是失败测试的简化版本:

@Test
public void testStringToClassList() {
    ObjectMapper objectMapper = new ObjectMapper();
    ObjectNode firstNode = new ObjectNode(JsonNodeFactory.instance);
    firstNode.set("startDate", JsonNodeFactory.instance.textNode("2020-12-01"));
    firstNode.set("endDate", JsonNodeFactory.instance.textNode("2020-12-02"));
    ObjectNode secondNode = new ObjectNode(JsonNodeFactory.instance);
    secondNode.set("startDate", JsonNodeFactory.instance.textNode("2020-12-10"));
    secondNode.set("endDate", JsonNodeFactory.instance.textNode("2020-12-11"));
    ArrayNode arrayNode = new ArrayNode(JsonNodeFactory.instance);
    arrayNode.add(firstNode);
    arrayNode.add(secondNode);
    String arrayString = "[{\"startDate\":\"2020-12-01\",\"endDate\":\"2020-12-02\"},{\"startDate\":\"2020-12-10\",\"endDate\":\"2020-12-11\"}]";
    List<?> objectList = ObjectNodeUtils.stringToClassList(arrayString, Object.class, objectMapper);
    Assert.assertEquals(arrayNode, objectMapper.valueToTree(objectList));
}

我理解这个问题与:

Arrays.asList(mapper.convertValue(mapper.readTree(data), Array.newInstance(convertType, 0).getClass()))

你知道怎么在这里列一张单子吗(我不太习惯编写泛型代码,但这似乎是一个很好的候选人)

zfycwa2u

zfycwa2u1#

不要重新发明轮子:

public static <T> List<T> stringToClassList(String data, Class<T> convertType, ObjectMapper mapper) {
    return mapper.readValue(data, mapper.getTypeFactory().constructCollectionType(List.class, convertType));
}

另请注意,从 List<?> (不太有用)到 List<T> (有用)。
您的测试方法也可以简化和改进:

@Test
public void testStringToClassList() {
    String input = "[\"foo\", \"bar\"]";
    List<String> expected = Arrays.asList("foo", "bar");
    Assert.assertEquals(expected, stringToClassList(input, String.class));
}
chy5wohz

chy5wohz2#

不要 Package 来自objectmapper的转换值结果。

public static <T> List<?> stringToClassList(String data, Class<T> convertType, ObjectMapper mapper) {
    if (!StringUtils.isBlank(data)) {
        try {
            if (mapper.readTree(data).size() != 0) {
                return mapper.convertValue(mapper.readTree(data), new TypeReference<List<T>>(){});
            }
        }
        catch (JsonProcessingException processingException) {
            LOGGER.error("Error coverting String to Json, Error: {}", processingException);
            throw new UnrecoverableRequestException(processingException);
        }
    }
    return Collections.EMPTY_LIST;
}

相关问题