Skip to content

Instantly share code, notes, and snippets.

@HydrangeaPurple
Created December 18, 2025 07:05
Show Gist options
  • Select an option

  • Save HydrangeaPurple/f3e3f9b3108febb6ac6551f04c88b8af to your computer and use it in GitHub Desktop.

Select an option

Save HydrangeaPurple/f3e3f9b3108febb6ac6551f04c88b8af to your computer and use it in GitHub Desktop.
java Map List 对象模板匹配拼装
package util;
import com.alibaba.fastjson2.JSON;
import util.ObjectIsNull;
import util.ObjectPathUtil.Rule;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.mvel2.MVEL;
import java.util.*;
/**
* 用来判断全局对象中是否满足了inOutEntity的定义
*
* @author cyq
* @version V1.0
* @since V1.0
*/
@SuppressWarnings("unchecked")
public class InOutEntityUtil {
/**
* 使用全局实例对象context, 根据样板对象inEntity, 来构建一个层级和key相同, value来自context的新map
*
* @param inEntity 样板对象(当有子结构时, 只考虑Map子结构, 不考虑List子结构)
* @param context 全局上下文对象
* @return 根据样板对象构建出来的新的对象, 新对象的Value只考虑Map和String
*/
public static EntityMatch getEntityFromContext(String inEntity, Map<String, Object> context) {
if (ObjectIsNull.check(inEntity)) {
return new EntityMatch(false, new HashMap<>());
}
Map<String, Object> inEntityMap = JSON.parseObject(inEntity, Map.class);
List<Rule> rules = WalkMapUtil.walkObj(inEntityMap);
boolean match = true;
Map<String, Object> result = new HashMap<>();
for (Rule rule : rules) {
Object exeValue = MVEL.eval(rule.mvelExpr(), context);
if (ObjectIsNull.check(exeValue)) {
match = false;
}
result = (Map<String, Object>) ObjectPathUtil.putValue(
result,
ObjectPathUtil.parsePath(rule.targetPath()),
exeValue
);
}
return new EntityMatch(match, result);
}
/**
* @param outEntity 样板对象
* @param context 全局上下文对象
* @return
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static Map<String, Object> extractOutEntity(String outEntity, Map<String, Object> context) {
Map<String, Object> result = new HashMap<>();
Map<String, Object> outEntityMap = JSON.parseObject(outEntity, Map.class);
List<Rule> rules = WalkMapUtil.walkObj(outEntityMap);
for (Rule rule : rules) {
Object exeValue = MVEL.eval(rule.mvelExpr(), context);
result = (Map<String, Object>) ObjectPathUtil.putValue(
result,
ObjectPathUtil.parsePath(rule.targetPath()),
exeValue
);
}
return result;
}
public static void main1(String[] args) {
// 测试案例1: 简单的键值对匹配
System.out.println("=== 测试案例1: 简单的键值对匹配 ===");
Map<String, Object> template1 = new HashMap<>();
template1.put("name", "string");
template1.put("age", "int");
Map<String, Object> context1 = new HashMap<>();
context1.put("name", "张三");
context1.put("age", "25");
context1.put("extra", "额外信息");
EntityMatch result1 = InOutEntityUtil.getEntityFromContext(JSON.toJSONString(template1), context1);
System.out.println("原始数据: " + context1);
System.out.println("模板: " + template1);
System.out.println("匹配结果: " + result1.isMatch());
System.out.println("提取数据: " + result1.getEntityFromContext());
// 测试案例2: 嵌套结构匹配
System.out.println("\n=== 测试案例2: 嵌套结构匹配 ===");
Map<String, Object> addressTemplate = new HashMap<>();
addressTemplate.put("street", "string");
addressTemplate.put("city", "string");
Map<String, Object> template2 = new HashMap<>();
template2.put("name", "string");
// template2.put("address", addressTemplate);
template2.put("address", "string");
Map<String, Object> addressContext = new HashMap<>();
addressContext.put("street", "中山路123号");
addressContext.put("city", "北京");
addressContext.put("zipcode", "100000");
Map<String, Object> context2 = new HashMap<>();
context2.put("name", "李四");
context2.put("address", addressContext);
context2.put("phone", "13800138000");
EntityMatch result2 = InOutEntityUtil.getEntityFromContext(JSON.toJSONString(template2), context2);
System.out.println("原始数据: " + context2);
System.out.println("模板: " + template2);
System.out.println("匹配结果: " + result2.isMatch());
System.out.println("提取数据: " + result2.getEntityFromContext());
// 测试案例3: 模板中有但上下文中没有的键
System.out.println("\n=== 测试案例3: 模板中有但上下文中没有的键 ===");
Map<String, Object> template3 = new HashMap<>();
template3.put("name", "string");
template3.put("email", "string"); // 上下文中没有email
Map<String, Object> context3 = new HashMap<>();
context3.put("name", "王五");
context3.put("phone", "13900139000");
EntityMatch result3 = InOutEntityUtil.getEntityFromContext(JSON.toJSONString(template3), context3);
System.out.println("原始数据: " + context3);
System.out.println("模板: " + template3);
System.out.println("匹配结果: " + result3.isMatch());
System.out.println("提取数据: " + result3.getEntityFromContext());
// 测试案例4: 空模板
System.out.println("\n=== 测试案例4: 空模板 ===");
Map<String, Object> template4 = new HashMap<>();
Map<String, Object> context4 = new HashMap<>();
context4.put("name", "赵六");
EntityMatch result4 = InOutEntityUtil.getEntityFromContext(JSON.toJSONString(template4), context4);
System.out.println("原始数据: " + context4);
System.out.println("模板: " + template4);
System.out.println("匹配结果: " + result4.isMatch());
System.out.println("提取数据: " + result4.getEntityFromContext());
// 测试案例5: List类型匹配
System.out.println("\n=== 测试案例5: List类型匹配 ===");
Map<String, Object> template5 = new HashMap<>();
template5.put("name", "string");
template5.put("hobbies", "list"); // List类型
Map<String, Object> context5 = new HashMap<>();
context5.put("name", "孙七");
context5.put("hobbies", java.util.List.of("读书", "游泳", "跑步"));
context5.put("age", 30);
EntityMatch result5 = InOutEntityUtil.getEntityFromContext(JSON.toJSONString(template5), context5);
System.out.println("原始数据: " + context5);
System.out.println("模板: " + template5);
System.out.println("匹配结果: " + result5.isMatch());
System.out.println("提取数据: " + result5.getEntityFromContext());
}
public static void main2(String[] args) {
String expr = """
[
"order": [
"createStaff": staff.createStaff,
"createOrgId": staff.createOrgId,
"latnId": latnId,
"goods": goods,
"cust": custInfo
]
]""";
Map<String, Object> env = new HashMap<>();
Map<String, Object> staff = new HashMap<>();
staff.put("createStaff", "10001");
staff.put("createOrgId", "20001");
env.put("staff", staff);
env.put("latnId", "3301");
env.put("goods", Collections.emptyList()); // List / Map 均可
env.put("custInfo", Collections.emptyMap()); // Map
Object result = MVEL.eval(expr, env);
Map<String, Object> resultMap = (Map<String, Object>) result;
System.out.println(resultMap);
}
public static void main3(String[] args) {
// 构造一个复杂的嵌套结构进行测试
Map<String, Object> complexMap = new HashMap<>();
// 添加简单键值对
complexMap.put("name", "张三");
complexMap.put("age", 25);
// 添加嵌套Map
Map<String, Object> address = new HashMap<>();
address.put("street", "中山路123号");
address.put("city", "北京");
complexMap.put("address", address);
// 添加嵌套List
List<String> hobbies = Arrays.asList("读书", "游泳", "跑步");
complexMap.put("hobbies", hobbies);
// 添加嵌套的复杂List(包含Map元素)
List<Map<String, Object>> contacts = new ArrayList<>();
Map<String, Object> contact1 = new HashMap<>();
contact1.put("type", "手机");
contact1.put("number", "13311111111");
contacts.add(contact1);
Map<String, Object> contact2 = new HashMap<>();
contact2.put("type", "邮箱");
contact2.put("address", "zhangsan@example.com");
contacts.add(contact2);
complexMap.put("contacts", contacts);
System.out.println(complexMap);
// 创建InOutEntityUtil实例并调用walk方法
System.out.println("遍历复杂嵌套结构:");
List<Rule> rules = WalkMapUtil.walkObj(complexMap);
System.out.println(JSON.toJSONString(rules));
Map<String, Object> outPut = new HashMap<>();
for (Rule rule : rules) {
outPut = (Map<String, Object>) ObjectPathUtil.putValue(
outPut,
ObjectPathUtil.parsePath(rule.targetPath()),
MVEL.eval(rule.mvelExpr(), complexMap)
);
}
System.out.println("生成的新对象:");
System.out.println(outPut);
}
public static void main(String[] args) {
String inEntity = "{\"event\":\"\",\"action\":\"\",\"goodsIntent\":\"list\", \"custId\": \"#cust.custId\"}";
Map<String, Object> context = new HashMap<>();
// 构造符合inEntity报文的上下文数据
context.put("event", "login");
context.put("action", "authenticate");
// 构造goodsIntent列表数据
List<Map<String, Object>> goodsIntent = new ArrayList<>();
Map<String, Object> goods1 = new HashMap<>();
goods1.put("id", "goods001");
goods1.put("name", "商品1");
goods1.put("price", 100);
goodsIntent.add(goods1);
Map<String, Object> goods2 = new HashMap<>();
goods2.put("id", "goods002");
goods2.put("name", "商品2");
goods2.put("price", 200);
goodsIntent.add(goods2);
context.put("goodsIntent", goodsIntent);
// 构造cust信息
Map<String, Object> cust = new HashMap<>();
cust.put("custId", "cust12345");
context.put("cust", cust);
// 调用getEntityFromContext方法
EntityMatch result = InOutEntityUtil.getEntityFromContext(inEntity, context);
System.out.println("输入的inEntity: " + inEntity);
System.out.println("构造的上下文: " + context);
System.out.println("匹配结果: " + result.isMatch());
System.out.println("提取的数据: " + result.getEntityFromContext());
}
@Data
@AllArgsConstructor
public static class EntityMatch {
boolean match;
Map<String, Object> entityFromContext;
}
}
package util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* [简要描述类的用途]
*
* <p>[更详细的说明,可以包括背景信息、用途等]</p>
*
* <p>注释中的段落使用 HTML 标签包裹,例如 `<p>` 或 `<ul>`。</p>
*
* @author cyq
* @version V1.0
* @since V1.0
*/
public class ObjectPathUtil {
public record Rule(String targetPath, String mvelExpr) {}
public sealed interface PathSeg permits KeySeg, IndexSeg {}
public record KeySeg(String key) implements PathSeg {}
public record IndexSeg(int index) implements PathSeg {}
public static List<PathSeg> parsePath(String path) {
List<PathSeg> result = new ArrayList<>();
int i = 0;
while (i < path.length()) {
if (path.charAt(i) == '.') {
i++;
continue;
}
if (path.charAt(i) == '[') {
int end = path.indexOf(']', i);
int index = Integer.parseInt(path.substring(i + 1, end));
result.add(new IndexSeg(index));
i = end + 1;
} else {
int start = i;
while (i < path.length()
&& path.charAt(i) != '.'
&& path.charAt(i) != '[') {
i++;
}
result.add(new KeySeg(path.substring(start, i)));
}
}
return result;
}
public static Object putValue(Object root, List<PathSeg> path, Object value) {
if (root == null) {
root = (path.get(0) instanceof IndexSeg) ? new ArrayList<>() : new HashMap<>();
}
Object current = root;
for (int i = 0; i < path.size(); i++) {
PathSeg seg = path.get(i);
boolean last = (i == path.size() - 1);
if (seg instanceof KeySeg keySeg) {
Map<String, Object> map = castMap(current);
if (last) {
map.put(keySeg.key(), value);
} else {
Object next = map.get(keySeg.key());
if (next == null) {
next = createNext(path.get(i + 1));
map.put(keySeg.key(), next);
}
current = next;
}
}
if (seg instanceof IndexSeg indexSeg) {
List<Object> list = castList(current);
int idx = indexSeg.index();
while (list.size() <= idx) {
list.add(null);
}
if (last) {
list.set(idx, value);
} else {
Object next = list.get(idx);
if (next == null) {
next = createNext(path.get(i + 1));
list.set(idx, next);
}
current = next;
}
}
}
return root;
}
private static Map<String, Object> castMap(Object o) {
if (o instanceof Map) return (Map<String, Object>) o;
throw new IllegalStateException("Expected Map but got " + o);
}
private static List<Object> castList(Object o) {
if (o instanceof List) return (List<Object>) o;
throw new IllegalStateException("Expected List but got " + o);
}
private static Object createNext(PathSeg nextSeg) {
return (nextSeg instanceof IndexSeg) ? new ArrayList<>() : new HashMap<>();
}
}
package util;
import java.util.*;
/**
* 遍历map得到结构
*
* @author cyq
* @version V1.0
* @since V1.0
*/
public class WalkMapUtil {
public static List<ObjectPathUtil.Rule> walkObj(Object node) {
List<ObjectPathUtil.Rule> rules = new ArrayList<>();
walk(node, new ArrayDeque<>(), rules);
return rules;
}
/**
* 遍历map得到结构
* @param node 原始参考对象
* @param path 临时保存路径的双端队列, 固定传 new ArrayDeque<>()
* @param rules 返回的对象结构清单
*/
private static void walk(Object node, Deque<String> path, List<ObjectPathUtil.Rule> rules) {
if (node instanceof Map) {
walkMap((Map<?, ?>) node, path, rules);
} else if (node instanceof List) {
walkList((List<?>) node, path, rules);
} else {
String buildPath = buildPath(path);
// 叶子节点(String / Number / Boolean / null 等)
String strNode = Objects.toString(node, "").trim();
String varName = extractVariableName(strNode);
if (varName != null) {
rules.add(new ObjectPathUtil.Rule(buildPath, varName));
} else {
rules.add(new ObjectPathUtil.Rule(buildPath, buildPath));
}
}
}
private static void walkMap(Map<?, ?> map, Deque<String> path, List<ObjectPathUtil.Rule> rules) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
String key = String.valueOf(entry.getKey());
path.addLast("." + key); // 进入
walk(entry.getValue(), path, rules);
path.removeLast(); // 退出
}
}
private static void walkList(List<?> list, Deque<String> path, List<ObjectPathUtil.Rule> rules) {
for (int i = 0; i < list.size(); i++) {
path.addLast("[" + i + "]");
walk(list.get(i), path, rules);
path.removeLast();
}
}
private static String buildPath(Deque<String> path) {
if (path.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
for (String p : path) {
sb.append(p);
}
// 去掉第一个点
return sb.charAt(0) == '.' ? sb.substring(1) : sb.toString();
}
private static String extractVariableName(String str) {
if (str.startsWith("#{") && str.endsWith("}")) {
// 匹配 #{varName} 格式
return str.substring(2, str.length() - 1);
} else if (str.startsWith("${") && str.endsWith("}")) {
// 匹配 ${varName} 格式
return str.substring(2, str.length() - 1);
} else if (str.startsWith("{") && str.endsWith("}")) {
// 匹配 {varName} 格式
return str.substring(1, str.length() - 1);
} else if (str.startsWith("[") && str.endsWith("]")) {
// 匹配 [varName] 格式
return str.substring(1, str.length() - 1);
} else if (str.startsWith("#") && str.endsWith("#")) {
// 匹配 #varName# 格式
return str.substring(1, str.length() - 1);
} else if (str.startsWith("$") && str.endsWith("$")) {
// 匹配 $varName$ 格式
return str.substring(1, str.length() - 1);
} else if (str.startsWith("#")) {
// 匹配 #varName 格式
return str.substring(1);
} else if (str.startsWith("$")) {
// 匹配 $varName 格式
return str.substring(1);
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment