将JSON数组值解析为POJO

时间:2017-07-07 13:18:49

标签: java json jackson

我需要处理来自外部SAP服务的响应,该服务将数据作为数组数组返回,如下所示:

{
    "INFO":"",
    "SERVICE_NAME":[["PARAM1","PARAM2","PARAM3","PARAM4"]],
    "RESULTS":[
        ["object1fieldValue1","object1fieldValue2"],
        ["object2fieldValue1","object2fieldValue2"]
    ]
}

我想进一步处理结果,作为这样的DTO列表:

public class ResultItemDto {
    private String field1;
    private String field2;
}

而不是将每个对象作为字符串列表使用,并可能将其手动映射到DTO。

将这样的JSON直接映射到POJO的简洁“杰克逊方式”是什么?

2 个答案:

答案 0 :(得分:2)

您可以使用@JsonFormat注释一个类,以表明它将在JSON中显示为数组:

@JsonFormat(shape = JsonFormat.Shape.ARRAY)
class ResultItemDto {
    private String field1;
    private String field2;
}

为验证上述内容,我为完整对象创建了一个包装类:

class ResultWrapper {
    private List<ResultItemDto> results;
}

并按照以下方式反序列化:

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);

ResultWrapper result = mapper.readValue(json, ResultWrapper.class);

使用ACCEPT_CASE_INSENSITIVE_PROPERTIES因为您的JSON具有大写名称的字段。

@JsonFormat及相关shapes

的文档

答案 1 :(得分:1)

“正确”的方式非常主观,但由于您对简洁方式感到好奇,因此您希望访问的字段包含在数组数组中,因此您的选项有限。鉴于这种结构,直接通过注释进行映射而不使用自定义反序列化器将是不可能的。您自定义解析的两个选项是databind api和流API。数据绑定API往往更容易读写,因此我们将使用它来满足您的简洁要求

下面是一些代码,它使用ObjectReader来解析json树,然后安全地使用JsonNode的pathisArrayNodeasText方法来获取这些内部数组的值。它们是预期的,如果您收到的json采用不同的结构,则不会导致异常。这假设您想要丢弃JSON主体的其余部分,因为您的问题仅讨论了专门针对ResultItemDto的映射。

package foo.bar;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.ArrayNode;

import java.util.ArrayList;
import java.util.List;

public class Test {

    static final String JSON = "{\n" +
                                       "    \"INFO\":\"\",\n" +
                                       "    \"SERVICE_NAME\":[[\"PARAM1\",\"PARAM2\",\"PARAM3\",\"PARAM4\"]],\n" +
                                       "    \"RESULTS\":[\n" +
                                       "        [\"object1fieldValue1\",\"object1fieldValue2\"],\n" +
                                       "        [\"object2fieldValue1\",\"object2fieldValue2\"]\n" +
                                       "    ]\n" +
                                       "}";

    static class ResultItemDto {
        private String field1;
        private String field2;
    }


    public static void main(String[] args) throws Exception {
        List<ResultItemDto> list = new ArrayList<ResultItemDto>();

        ObjectReader reader = new ObjectMapper().reader();
        JsonNode resultsNode = reader.readTree(JSON).path("RESULTS");
        if (resultsNode.isArray()) {
            ArrayNode arrNode = (ArrayNode) resultsNode;
            arrNode.elements().forEachRemaining(elem -> {
                ResultItemDto dto = new ResultItemDto()
                dto.field1 = elem.path(0).asText();
                dto.field2 = elem.path(1).asText();
                list.add(dto);
            });
        }
    }
}

如果你想注释你的DTO类,一旦你用@JsonDeserialize注释了dto,就可以在自定义反序列化器中使用上面的代码,并且可以在JsonParser上调用readTree方法反序列化时必须使用。