package tqq9.lc123.cloud.app.api.utils; import com.fasterxml.jackson.databind.JsonNode; import tqq9.lc123.cloud.app.api.utils.mapping.GyDeliveryMapping; import java.util.*; /** * 把 delivery 节点全部拍扁 */ public final class GyDeliverySyncMappingUtil { /* 1. 缓存:key = 全路径,value = 值或List */ private static final Map CACHE = new HashMap<>(); /* 2. 入口 */ public static void parse(JsonNode delivery) { CACHE.clear(); flatten(null, delivery); } /* 3. 统一取值 */ public static Object get(String outerKey) { String path = GyDeliveryMapping.FIELD_MAP.get(outerKey); if (path == null) return null; /* 3.1 整段数组或对象 */ if (isWholeBlock(path)) return CACHE.get(path); /* 3.2 数组模板:details[].field 或 details[1].field */ if (path.contains("[") && path.contains("].")) { return handleArrayTemplate(path); } /* 3.3 普通根字段 */ return CACHE.get(path); } /* 4. 拍扁:对象展开;数组既存整段,又明细到 CACHE */ private static void flatten(String parent, JsonNode node) { if (node.isObject()) { Iterator> it = node.fields(); while (it.hasNext()) { Map.Entry e = it.next(); flatten(join(parent, e.getKey()), e.getValue()); } } else if (node.isArray()) { List> list = new ArrayList<>(); for (int i = 0; i < node.size(); i++) { JsonNode child = node.get(i); Map row = new LinkedHashMap<>(); Iterator> it = child.fields(); while (it.hasNext()) { Map.Entry f = it.next(); String key = f.getKey(); Object val = convert(f.getValue()); row.put(key, val); /* 字段别名:item_code -> material */ String alias = GyDeliveryMapping.ALIAS_MAP.get(key); if (alias != null) row.put(alias, val); } list.add(row); /* 明细拍扁:details[0].xxx */ String idxKey = parent + "[" + i + "]"; for (Map.Entry entry : row.entrySet()) { CACHE.put(idxKey + "." + entry.getKey(), entry.getValue()); } } CACHE.put(parent, list); // 整段也保留 } else { CACHE.put(parent, convert(node)); } } /* 5. 数组模板处理 */ private static Object handleArrayTemplate(String path) { int dot = path.indexOf("]."); String listPart = path.substring(0, dot + 1); String field = path.substring(dot + 2); String listKey = listPart.substring(0, listPart.indexOf("[")); Object block = CACHE.get(listKey); if (!(block instanceof List)) return null; List> list = (List>) block; String idxPart = listPart.substring(listPart.indexOf("[") + 1, listPart.length() - 1); /* 5.1 通配:details[].field */ if (idxPart.isEmpty()) { List res = new ArrayList<>(list.size()); for (Map row : list) { res.add(row.get(field)); } return res; } /* 5.2 单条:details[1].field */ int i = Integer.parseInt(idxPart); return i < 0 || i >= list.size() ? null : list.get(i).get(field); } /* 6. 工具方法 */ private static boolean isWholeBlock(String path) { return path.equals("details") || path.equals("payments") || path.equals("invoices") || path.equals("tags") || path.equals("stock_location") || path.equals("delivery_statusInfo") || path.equals("store_info"); } private static String join(String parent, String key) { return parent == null ? key : parent + "." + key; } private static Object convert(JsonNode n) { if (n.isTextual()) return n.asText(); if (n.isNumber()) return n.isFloatingPointNumber() ? n.asDouble() : n.asLong(); if (n.isBoolean()) return n.asBoolean(); return n.asText(); } }