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

Java JSON解析器解析含原生JS调用的内容失败,如何解决?

你遇到的解析失败是因为待解析内容不属于标准JSON格式,而是JavaScript对象字面量,存在两处不符合JSON规范的问题:

  • 所有键名没有使用双引号包裹
  • cb字段的值是需要浏览器运行时执行的JS表达式,不属于JSON支持的字符串、数字、布尔值、数组、对象、null六种基础类型

以下是三种可行的适配方案:

方案1:使用Java内嵌JS引擎解析(最稳定,支持读取所有字段)

可以用GraalJS、Rhino等Java支持的JS运行引擎,直接把这段内容作为JS代码执行,提前模拟好浏览器的location对象即可拿到完整的对象数据,示例代码如下:

// GraalJS 依赖(Maven)
// <dependency>
//     <groupId>org.graalvm.js</groupId>
//     <artifactId>js</artifactId>
//     <version>22.3.0</version>
// </dependency>
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class ParseJsObjectDemo {
    public static void main(String[] args) {
        // 待解析的JS对象内容
        String jsObjStr = "{\n" +
                "    data: {\n" +
                "        data1: {\n" +
                "            plugins: ['voip', 'speed', 'act', 'capacity'],\n" +
                "            last: \"~last~\",\n" +
                "            unit: \"~units~\",\n" +
                "            sid: '~sessionid~',\n" +
                "            by: \"~by~\"\n" +
                "        }\n" +
                "    },\n" +
                "    cb: location.protocol + \"//\" + location.host,\n" +
                "    thresholds: ['default'],\n" +
                "    calendars: ['default']\n" +
                "}";
        // 提前模拟浏览器环境的location对象,可根据实际需求设置对应值
        String mockBrowserEnv = "const location = {protocol: 'https:', host: 'www.example.com'};";

        try (Context jsContext = Context.create("js")) {
            // 先注入模拟的浏览器环境变量
            jsContext.eval("js", mockBrowserEnv);
            // 执行JS代码拿到对象,加括号是为了避免解析为代码块
            Value parseResult = jsContext.eval("js", "(" + jsObjStr + ")");
            
            // 读取字段示例
            String cbValue = parseResult.getMember("cb").asString();
            Value data1 = parseResult.getMember("data").getMember("data1");
            String sidValue = data1.getMember("sid").asString();

            System.out.println("cb字段值:" + cbValue);
            System.out.println("sid字段值:" + sidValue);
        }
    }
}

方案2:文本预处理后用标准JSON库解析(适合不需要cb字段的场景)

如果不需要读取cb字段的值,可以通过简单的字符串替换把内容转换为标准JSON,再用Jackson、Fastjson等常规JSON库解析:

  1. 把所有单引号替换为双引号
  2. 给所有未加双引号的键名包裹双引号
  3. 把cb: location.protocol + "//" + location.host,整段替换为cb: "",
    处理完成后的内容就符合JSON规范,可以直接用常规解析器解析。

方案3:开启JSON库的宽松解析特性

常用JSON库都支持宽松解析模式,比如Jackson开启以下特性后可以解析无引号键名、单引号值的非标准JSON:

  • JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES:允许键名不加双引号
  • JsonParser.Feature.ALLOW_SINGLE_QUOTES:允许值使用单引号包裹
    开启后仍需要提前把cb字段的表达式替换为合法JSON值,才能完成解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:18:03