意图
我正在使用 Java 8u60(不是 8u51,这很重要!)并且正在使用其 Nashorn JavaScript 引擎。我通过扩展 AbstractJSObject
创建了自己的 JSObject
。它应该包装一个 org.json.JSONObject 并使其像脚本引擎中的实际 JavaScript 对象一样工作。鉴于 javaAPI
是一个放入 ScriptContext
中的 Java 对象,生成的对象应该如下所示:
var jsonObject = javaAPI.doSomethingThatReturnsAJSONObject();
var foo = jsonObject.foo
jsonObject.foo = "bar";
delete jsonObject.foo;
var message = "JSON: " + jsonObject;
代码
public class JSONObjectJavaScriptAdapter extends AbstractJSObject {
private final JSONObject jsonObject;
public JSONObjectJavaScriptAdapter(final JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
@Override
public void removeMember(String name) {
jsonObject.remove(name);
}
@Override
public void setMember(String name, Object value) {
jsonObject.put(name, value);
}
@Override
public Set<String> keySet() {
return jsonObject.keySet();
}
@Override
public boolean hasMember(String name) {
return jsonObject.has(name);
}
@Override
public Object getMember(String name) {
return jsonObject.get(name);
}
@Override
public String toString() {
return jsonObject.toString();
}
}
问题
除了字符串连接之外,一切正常。写一些类似的东西
var message = "JSON: " + jsonObject;
将导致以下异常:
org.json.JSONException: JSONObject["valueOf"] not found.
at org.json.JSONObject.get(JSONObject.java:476)
at my.JSONObjectJavaScriptAdapter.getMember(JSONObjectJavaScriptAdapter.java:50)
at jdk.nashorn.api.scripting.DefaultValueImpl.getDefaultValue(DefaultValueImpl.java:42)
at jdk.nashorn.api.scripting.AbstractJSObject.getDefaultValue(AbstractJSObject.java:269)
at jdk.nashorn.api.scripting.AbstractJSObject.getDefaultValue(AbstractJSObject.java:285)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:512)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:480)
at jdk.nashorn.internal.runtime.JSType.toPrimitive(JSType.java:462)
at jdk.nashorn.internal.runtime.ScriptRuntime.ADD(ScriptRuntime.java:563)
at jdk.nashorn.internal.scripts.Script$Recompilation$2$16$configuration.main(src/test/resources/de/ams/inm/workflow/engine/javascript/async/configuration.js:23)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:199)
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeImpl(NashornScriptEngine.java:383)
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeFunction(NashornScriptEngine.java:190)
[...]
我需要做什么才能让 Nashorn 调用 toString()
方法,以便 message
包含类似 JSON: {"foo":"的内容栏}
?
最佳答案
解决方案
事实证明,Nashorn 严格遵循 ECMA 规范。重要的部分是The Addition operator ( + )和 [[DefaultValue]] .
如果对对象使用 + 运算符,这些对象将使用 [[DefaultValue]] 函数转换为基元。默认的 [[DefaultValue]] 实现通过使用 valueOf
或 toString
函数将对象转换为基元。
对象可以覆盖 [[DefaultValue]] 函数以提供自定义到基元的转换。从 Java 8u60 开始,通过重写 AbstractJSObject.getDefaultValue(Class)
,这也可能出现在 Nashorn 中。
我将以下代码添加到 JSONObjectJavaScriptAdapter
以使字符串连接正常工作:
@Override
public Object getDefaultValue(Class<?> hint) {
return toString();
}
关于javascript - 如何使用 Nashorn 的 JSObject 进行字符串连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32307231/