You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中JSON对象表达式求值实现方案咨询

Java中JSON对象内表达式求值的实现方案

需求说明

源JSON包含三类需要求值的表达式:

  • 纯算术表达式(如${a}*${b})
  • 字符串拼接(如${model}-${variant})
  • 拼接与算术组合(如${model}-${variant}-${stage*10})

源JSON:

{"model":"abc","variant":"m1","stage":2,"a":100,"b":200,"display name":"${model}-${variant}","c":"${a}*${b}","description":"${model}-${variant}-${stage*10}"}

求值后目标JSON:

{"model":"abc","variant":"m1","stage":2,"a":100,"b":200,"display name":"abc-m1","c":"300","description":"abc-m1-20"}

可行实现方案

方案一:模板引擎+表达式求值库组合

用模板引擎处理字符串拼接逻辑,搭配表达式库完成算术运算,步骤如下:

  1. 选Apache Velocity或Freemarker做模板引擎,解析带变量占位符的字符串;
  2. 用Apache Commons JEXL或MVEL做表达式求值库,处理算术计算;
  3. 遍历JSON字段,先提取并计算算术子表达式,再用模板引擎渲染完整字符串;
  4. 将渲染结果替换回JSON,生成目标结构。

示例代码片段(JEXL+Velocity):

// 初始化JEXL引擎
JexlEngine jexl = new JexlEngine();
// 初始化Velocity引擎
Velocity.init();
VelocityContext velocityContext = new VelocityContext();

// 解析源JSON为Map(依赖Jackson)
Map<String, Object> sourceMap = new ObjectMapper().readValue(sourceJson, Map.class);
sourceMap.forEach(velocityContext::put);

// 遍历处理每个字段
sourceMap.forEach((key, value) -> {
    if (value instanceof String strValue) {
        Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
        Matcher matcher = pattern.matcher(strValue);
        StringBuffer result = new StringBuffer();

        while (matcher.find()) {
            String expr = matcher.group(1);
            if (expr.matches(".*[+\\-*/].*")) {
                // 计算算术表达式
                JexlExpression jexlExpr = jexl.createExpression(expr);
                Object evalResult = jexlExpr.evaluate(new MapContext(sourceMap));
                matcher.appendReplacement(result, evalResult.toString());
            } else {
                // 保留变量占位符给Velocity处理
                matcher.appendReplacement(result, matcher.group(0));
            }
        }

        // 用Velocity渲染最终字符串
        String processedExpr = matcher.appendTail(result).toString();
        StringWriter writer = new StringWriter();
        Velocity.evaluate(velocityContext, writer, "", processedExpr);
        sourceMap.put(key, writer.toString());
    }
});

// 转换回JSON字符串
String targetJson = new ObjectMapper().writeValueAsString(sourceMap);

方案二:自定义解析+JS引擎计算

不想引入过多第三方库时,可借助Java内置的ScriptEngine实现:

  1. 用正则提取${}内的表达式内容;
  2. 尝试用JS引擎计算表达式,失败则视为变量引用直接取值;
  3. 替换所有表达式后更新JSON字段。

示例代码片段:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Map<String, Object> sourceMap = new ObjectMapper().readValue(sourceJson, Map.class);

sourceMap.forEach((key, value) -> {
    if (value instanceof String strValue) {
        Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
        Matcher matcher = pattern.matcher(strValue);
        StringBuffer result = new StringBuffer();

        while (matcher.find()) {
            String expr = matcher.group(1);
            Object evalResult;
            try {
                // 尝试计算表达式
                evalResult = engine.eval(expr, new SimpleBindings(sourceMap));
            } catch (ScriptException e) {
                // 计算失败则直接取变量值
                evalResult = sourceMap.get(expr);
            }
            matcher.appendReplacement(result, evalResult.toString());
        }

        sourceMap.put(key, matcher.appendTail(result).toString());
    }
});

String targetJson = new ObjectMapper().writeValueAsString(sourceMap);

方案三:使用支持表达式的JSON库

部分JSON库内置表达式求值能力,比如Jsonata的Java实现,可直接解析源JSON中的表达式并生成目标结构,无需拆分处理步骤。


内容的提问来源于stack exchange,提问作者Pranav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:35:44