我需要处理来自外部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的简洁“杰克逊方式”是什么?
答案 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具有大写名称的字段。
答案 1 :(得分:1)
“正确”的方式非常主观,但由于您对简洁方式感到好奇,因此您希望访问的字段包含在数组数组中,因此您的选项有限。鉴于这种结构,直接通过注释进行映射而不使用自定义反序列化器将是不可能的。您自定义解析的两个选项是databind api和流API。数据绑定API往往更容易读写,因此我们将使用它来满足您的简洁要求
下面是一些代码,它使用ObjectReader来解析json树,然后安全地使用JsonNode的path
,isArrayNode
和asText
方法来获取这些内部数组的值。它们是预期的,如果您收到的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
方法反序列化时必须使用。