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

Java中如何计算JSON对象内的表达式?

在Java中计算JSON对象内的表达式

我们需要解析JSON对象,将其中形如calc(表达式)的字符串替换为对应表达式的计算结果——比如把"calc(a+c)"换成400(当a=100、c=300时)。之前尝试的工具不满足需求,这里可以用**Jackson(JSON解析)+ Apache Commons JEXL(表达式计算)**组合实现。


一、依赖准备

如果用Maven,在pom.xml中添加以下依赖:

<!-- Jackson 用于JSON解析与修改 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>
<!-- Apache Commons JEXL 用于解析计算表达式 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-jexl3</artifactId>
    <version>3.3</version>
</dependency>

二、核心实现逻辑

  1. 用Jackson将源JSON解析为可修改的ObjectNode;
  2. 递归遍历所有JSON节点:
    • 识别字符串节点中符合calc(...)格式的内容;
    • 提取括号内的表达式,收集当前节点层级的所有数值型键值对作为计算上下文;
    • 用JEXL计算表达式结果,将原字符串节点替换为数值节点;
  3. 将修改后的ObjectNode转回格式化的JSON字符串。

三、完整代码示例

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.MapContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonExpressionEvaluator {
    // 匹配calc(...)格式的正则表达式
    private static final Pattern CALC_PATTERN = Pattern.compile("^calc\\((.*)\\)$");
    // 初始化JEXL表达式引擎
    private static final JexlEngine JEXL_ENGINE = new JexlBuilder().create();

    public static void main(String[] args) throws Exception {
        // 源JSON字符串
        String sourceJson = """
                {
                  "a": 100,
                  "b": 200,
                  "c": 300,
                  "d": "calc(a+c)",
                  "f": {
                    "g": 100,
                    "h": 200,
                    "i": "calc(g+h)"
                  }
                }
                """;

        ObjectMapper mapper = new ObjectMapper();
        // 解析为可修改的ObjectNode
        ObjectNode rootNode = (ObjectNode) mapper.readTree(sourceJson);

        // 递归处理所有节点
        processNode(rootNode);

        // 输出格式化后的结果JSON
        String resultJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode);
        System.out.println(resultJson);
    }

    private static void processNode(ObjectNode node) {
        // 遍历当前节点的所有字段
        node.fields().forEachRemaining(entry -> {
            JsonNode valueNode = entry.getValue();
            if (valueNode.isObject()) {
                // 子节点是对象,递归处理
                processNode((ObjectNode) valueNode);
            } else if (valueNode.isTextual()) {
                String text = valueNode.asText();
                Matcher matcher = CALC_PATTERN.matcher(text);
                if (matcher.find()) {
                    // 提取括号内的表达式内容
                    String exprStr = matcher.group(1);
                    // 构建当前节点的计算上下文(仅包含数值类型的键值对)
                    JexlContext context = new MapContext();
                    node.fields().forEachRemaining(field -> {
                        JsonNode fieldValue = field.getValue();
                        if (fieldValue.isNumber()) {
                            context.set(field.getKey(), fieldValue.asDouble());
                        }
                    });
                    // 计算表达式结果
                    Object result = JEXL_ENGINE.createExpression(exprStr).evaluate(context);
                    // 将原字符串节点替换为数值节点
                    if (result instanceof Number) {
                        node.put(entry.getKey(), ((Number) result).intValue());
                    }
                }
            }
        });
    }
}

四、运行结果

执行代码后,输出的JSON与预期完全一致:

{
  "a" : 100,
  "b" : 200,
  "c" : 300,
  "d" : 400,
  "f" : {
    "g" : 100,
    "h" : 200,
    "i" : 300
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:15:37