Javascript 如何使用Nashorn';JSS对象 意图

Javascript 如何使用Nashorn';JSS对象 意图,javascript,java,nashorn,Javascript,Java,Nashorn,我使用的是Java8U60(不是8u51,这很重要!),我正在使用它的Nashorn JavaScript引擎。我通过扩展AbstractJSObject创建了自己的JSObject。它应该包装一个org.json.JSONObject,使其像脚本引擎中的实际JavaScript对象一样工作。假设javaAPI是一个放入ScriptContext的Java对象,那么生成的对象应该是如下所示的可用对象: var jsonObject = javaAPI.doSomethingThatReturns

我使用的是Java8U60(不是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;
代码 将导致以下异常:

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()
方法,这样
消息
将包含类似于
JSON:{“foo”:“bar}
的内容?

解决方案 事实证明,Nashorn严格遵循ECMA规范。重要的部分是和

如果对象使用+运算符,则这些对象将使用[[DefaultValue]]函数转换为基本体。默认[[DefaultValue]]实现通过使用
valueOf
toString
函数将对象转换为基本体

对象可以重写[[DefaultValue]]函数以提供自定义到原语的转换。由于Java 8u60,这也可能在Nashorn中,通过重写
AbstractJSObject.getDefaultValue(类)

我在
JSONObjectJavaScriptAdapter
中添加了以下代码,以使字符串连接正常工作:

@Override
public Object getDefaultValue(Class<?> hint) {
    return toString();
}
@覆盖
公共对象getDefaultValue(类提示){
返回到字符串();
}

另外,如果JSObject.getMember可以处理抛出的任何异常,并可能返回null或适当的值,而不是传播异常。在您的示例中,org.json.JSONObject.get在找不到属性时抛出异常


另一件事:您可以为“toString”或“valueOf”属性返回一个“function value”,这样它就可以按照ECMAScript中的指定为toString/toNumber转换而被调用。

您是对的,我应该在
getMember(String)
中捕获异常。虽然我知道“function value”,但我认为重写
getDefaultValue(Class)
在Nashorn的上下文中要简单得多。
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)
    [...]
@Override
public Object getDefaultValue(Class<?> hint) {
    return toString();
}