Java中如何高效提取含Map与List子结构的嵌套Map指定键值对?
高效提取嵌套Map/JSON数据的优化方案
问题描述
我有一个API返回的嵌套Map(对应如下JSON结构):
{ "code": 200, "status_message": "OK", "category_list": [ { "category_name": "fragile", "results": [ { "item_id": "001A", "item_name": "glass", "certificate_id": "A9812EJ0D7CBN12109" }, { "item_id": "002A", "item_name": "porcelain", "certificate_id": "BCQ8018347503048P1" } ] }, { "category_name": "hard", "results": [ { "item_id": "001B", "item_name": "rock", "certificate_id": "P1024184INDHDGA831" }, { "item_id": "002B", "item_name": "diamond", "certificate_id": "YDQI3910371H7D39ZX" } ] } ] }
需求是仅提取fragile分类下results中的item_name与item_id,并将键名改为name和id,最终输出JSON结构如下:
{ "code": 200, "results": [ { "id": "001A", "name": "glass" }, { "id": "002A", "name": "porcelain" } ] }
目前我用原生Java代码处理(将API结果存在Map类型的apiResult变量中),但面对更复杂的嵌套结构时,这种写法会变得繁琐,想咨询更高效的扁平化/简化处理方案。
现有实现代码
List results = ((Map) ((List) apiResult.get("category_list")).get(0)).get("results"); List finalResult = new ArrayList<>(); for(Object r : results) { Map inner = new HashMap(); inner.put("name", ((Map)r).get("item_name")); inner.put("id", ((Map)r).get("item_id")); finalResult.add(inner); } Map result = new HashMap(); result.put("code", 200); result.put("results", finalResult); return result;
优化方案
1. 使用Stream API简化循环逻辑
如果你还是想用原生集合操作,Stream API可以让代码更简洁,同时避免强制类型转换的冗余,还能加入空值安全处理:
// 先过滤出category_name为fragile的分类 Optional<Map<String, Object>> fragileCategory = ((List<Map<String, Object>>) apiResult.get("category_list")) .stream() .filter(cat -> "fragile".equals(cat.get("category_name"))) .findFirst(); if (fragileCategory.isPresent()) { List<Map<String, Object>> transformedResults = ((List<Map<String, Object>>) fragileCategory.get().get("results")) .stream() .map(item -> { Map<String, Object> newItem = new HashMap<>(); newItem.put("id", item.get("item_id")); newItem.put("name", item.get("item_name")); return newItem; }) .collect(Collectors.toList()); Map<String, Object> finalResult = new HashMap<>(); finalResult.put("code", apiResult.get("code")); // 复用原API的code,更灵活 finalResult.put("results", transformedResults); return finalResult; } // 处理未找到fragile分类的情况 Map<String, Object> emptyResult = new HashMap<>(); emptyResult.put("code", 404); emptyResult.put("results", Collections.emptyList()); return emptyResult;
这种写法比直接取索引get(0)更健壮,能应对第一个分类不是fragile的场景。
2. 自定义POJO + Jackson ObjectMapper(推荐用于复杂结构)
对于复杂嵌套结构,用POJO(普通Java对象)映射是最清晰、可维护的方案,配合Jackson库可以自动完成序列化/反序列化,彻底摆脱手动操作Map的繁琐:
首先定义对应的POJO类:
// 原API返回的顶层结构 class ApiResponse { private int code; private String status_message; private List<Category> category_list; // 生成getter、setter public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getStatus_message() { return status_message; } public void setStatus_message(String status_message) { this.status_message = status_message; } public List<Category> getCategory_list() { return category_list; } public void setCategory_list(List<Category> category_list) { this.category_list = category_list; } } // 分类结构 class Category { private String category_name; private List<Item> results; // 生成getter、setter public String getCategory_name() { return category_name; } public void setCategory_name(String category_name) { this.category_name = category_name; } public List<Item> getResults() { return results; } public void setResults(List<Item> results) { this.results = results; } } // 原商品项结构 class Item { private String item_id; private String item_name; private String certificate_id; // 生成getter、setter public String getItem_id() { return item_id; } public void setItem_id(String item_id) { this.item_id = item_id; } public String getItem_name() { return item_name; } public void setItem_name(String item_name) { this.item_name = item_name; } public String getCertificate_id() { return certificate_id; } public void setCertificate_id(String certificate_id) { this.certificate_id = certificate_id; } } // 最终输出的结构 class FinalResponse { private int code; private List<FinalItem> results; // 构造方法+getter、setter public FinalResponse(int code, List<FinalItem> results) { this.code = code; this.results = results; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public List<FinalItem> getResults() { return results; } public void setResults(List<FinalItem> results) { this.results = results; } } // 最终输出的商品项结构 class FinalItem { private String id; private String name; public FinalItem(String id, String name) { this.id = id; this.name = name; } // 生成getter、setter public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
然后处理逻辑会变得非常简洁:
ObjectMapper mapper = new ObjectMapper(); // 将apiResult转换为ApiResponse对象 ApiResponse response = mapper.convertValue(apiResult, ApiResponse.class); // 找到fragile分类并转换结果 Optional<List<FinalItem>> transformedItems = response.getCategory_list().stream() .filter(cat -> "fragile".equals(cat.getCategory_name())) .findFirst() .map(Category::getResults) .map(items -> items.stream() .map(item -> new FinalItem(item.getItem_id(), item.getItem_name())) .collect(Collectors.toList())); // 构建最终响应 FinalResponse finalResponse = new FinalResponse( response.getCode(), transformedItems.orElse(Collections.emptyList()) ); // 如果需要返回Map,再转换回去;如果直接返回JSON,用mapper.writeValueAsString(finalResponse) return mapper.convertValue(finalResponse, Map.class);
这种方式的优势在于类型安全、可读性强,面对更复杂的嵌套结构时,只需要扩展POJO即可,维护成本极低。
3. 使用JsonPath直接提取(适合快速查询)
如果只是需要快速提取特定路径的数据,JsonPath库可以直接通过路径表达式定位目标,无需手动遍历:
// 将apiResult转换为JsonNode JsonNode root = JsonPath.parse(apiResult).json(); // 提取fragile分类下的所有商品项 List<Map<String, Object>> fragileResults = JsonPath.read(root, "$.category_list[?(@.category_name == 'fragile')].results[*]"); // 转换键名 List<Map<String, Object>> transformedResults = fragileResults.stream() .map(item -> { Map<String, Object> newItem = new HashMap<>(); newItem.put("id", item.get("item_id")); newItem.put("name", item.get("item_name")); return newItem; }) .collect(Collectors.toList()); // 构建最终结果 Map<String, Object> finalResult = new HashMap<>(); finalResult.put("code", JsonPath.read(root, "$.code")); finalResult.put("results", transformedResults); return finalResult;
JsonPath的路径表达式$.category_list[?(@.category_name == 'fragile')].results[*]可以直接定位到目标数据,非常适合临时需求或结构不固定的场景。
内容的提问来源于stack exchange,提问作者Dhana D.
相关产品推荐
相关产品推荐

