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

如何在Java中序列化包含JavaScript函数的JavaScript对象?

在Java中序列化包含JavaScript函数的JS对象字面量

首先要明确:你要生成的是JavaScript对象字面量,而非严格符合JSON规范的内容——因为标准JSON并不支持函数类型。org.json库是严格遵循JSON规范的,所以默认无法直接输出函数,需要通过自定义逻辑来实现。

以下是几种可行的解决方案:

方案1:自定义函数封装类 + 字符串替换(轻量快速)

先定义一个封装JS函数的类,重写其toString方法输出函数的原生代码:

public class JsFunction {
    private final String args;
    private final String body;

    public JsFunction(String args, String body) {
        this.args = args;
        this.body = body;
    }

    @Override
    public String toString() {
        return String.format("function (%s) {\n    %s\n}", args, body);
    }
}

之后使用org.json生成初始JSON字符串,再替换掉函数内容的包裹引号:

import org.json.JSONObject;

public class Main {
    public static void main(String[] args) {
        JSONObject obj = new JSONObject();
        obj.put("foo", "bar");
        obj.put("baz", new JsFunction("x, y", "return x+y;"));

        // 生成带引号包裹函数的JSON字符串
        String rawJson = obj.toString(2);
        // 替换引号,得到原生JS对象字面量
        String jsObject = rawJson.replace("\"function (", "function (")
                                .replace("}\"", "}");
        
        System.out.println(jsObject);
    }
}

输出结果就是你期望的格式:

{
  "foo": "bar",
  "baz": function (x, y) {
    return x+y;
  }
}

方案2:扩展org.json的JSONWriter(更优雅的定制)

org.json的序列化依赖JSONWriter,可以自定义Writer来识别JsFunction类型并直接输出原生代码:

import org.json.JSONWriter;
import java.io.IOException;
import java.io.StringWriter;

public class JsObjectWriter extends JSONWriter {
    public JsObjectWriter(StringWriter writer) {
        super(writer);
    }

    @Override
    public JSONWriter value(Object value) throws IOException {
        if (value instanceof JsFunction) {
            // 直接写入函数内容,不添加JSON字符串的引号包裹
            this.writer.write(value.toString());
            return this;
        }
        return super.value(value);
    }
}

使用自定义Writer生成内容:

import java.io.StringWriter;

public class Main {
    public static void main(String[] args) throws IOException {
        StringWriter sw = new StringWriter();
        JsObjectWriter writer = new JsObjectWriter(sw);
        
        writer.object();
        writer.key("foo").value("bar");
        writer.key("baz").value(new JsFunction("x, y", "return x+y;"));
        writer.endObject();

        String jsObject = sw.toString();
        System.out.println(jsObject);
    }
}

这个方案无需后续字符串替换,直接生成目标内容,适合需要频繁生成这类对象的场景。

方案3:切换到支持原生JS输出的库(健壮性更高)

如果你的项目可以引入其他库,Jackson是更好的选择——它支持自定义序列化器输出原生JS代码:

首先定义JsFunction类和对应的序列化器:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;

public class JsFunction {
    private final String args;
    private final String body;

    public JsFunction(String args, String body) {
        this.args = args;
        this.body = body;
    }

    public String getArgs() {
        return args;
    }

    public String getBody() {
        return body;
    }
}

class JsFunctionSerializer extends StdSerializer<JsFunction> {
    public JsFunctionSerializer() {
        super(JsFunction.class);
    }

    @Override
    public void serialize(JsFunction value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 使用writeRawValue输出原生JS代码,不转义
        String funcStr = String.format("function (%s) {\n    %s\n}", value.getArgs(), value.getBody());
        gen.writeRawValue(funcStr);
    }
}

然后配置Jackson并生成内容:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        // 注册自定义序列化器
        SimpleModule module = new SimpleModule();
        module.addSerializer(new JsFunctionSerializer());
        mapper.registerModule(module);

        Map<String, Object> jsObj = new HashMap<>();
        jsObj.put("foo", "bar");
        jsObj.put("baz", new JsFunction("x, y", "return x+y;"));

        // 生成格式化后的JS对象字面量
        String jsObject = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsObj);
        System.out.println(jsObject);
    }
}

注意事项

  • 生成的内容不是标准JSON,无法被JSON解析器正确解析,仅适用于JavaScript环境。
  • 如果函数体包含特殊字符(如换行、引号),需要自行处理转义,避免破坏JS语法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:30:32