我正在使用Java 8u60(不 8u51,这很重要!)并正在使用其Nashorn JavaScript引擎。我通过扩展AbstractJSObject
创建了自己的org.json.JSONObject
。它应该包装javaAPI
并使其像脚本引擎中的实际JavaScript对象一样工作。鉴于ScriptContext
是放在var jsonObject = javaAPI.doSomethingThatReturnsAJSONObject();
var foo = jsonObject.foo
jsonObject.foo = "bar";
delete jsonObject.foo;
var message = "JSON: " + jsonObject;
中的Java对象,生成的对象应该像这样使用:
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)
[...]
将导致以下异常:
toString()
我需要做些什么才能让Nashorn调用message
方法,以便JSON: {"foo":"bar}
包含{{1}}之类的内容?
答案 0 :(得分:2)
事实证明,Nashorn遵循ECMA规范。重要的部分是The Addition operator ( + )和[[DefaultValue]]。
如果+运算符用于对象,则使用[[DefaultValue]]函数将这些对象转换为基元。默认[[DefaultValue]]实现使用valueOf
或toString
函数将对象转换为基元。
对象可以覆盖[[DefaultValue]]函数以提供自定义到基元的转换。从Java 8u60开始,这也可能在Nashorn中,通过覆盖AbstractJSObject.getDefaultValue(Class)
。
我将以下代码添加到JSONObjectJavaScriptAdapter
以使字符串连接工作为例外:
@Override
public Object getDefaultValue(Class<?> hint) {
return toString();
}
答案 1 :(得分:0)
此外,如果JSObject.getMember可以处理任何抛出的异常,并且可能返回null或适当的值 - 而不是传播异常。在您的示例中,org.json.JSONObject.get在未找到属性时抛出异常。
另一件事:你可以返回一个&#39;函数值&#39;为&#39; toString&#39;或者&#39; valueOf&#39; property - 以便按ECMAScript中的指定调用toString / toNumber转换。