javascript - How to make string concatenation work with Nashorn's JSObject -
intention
i'm using java 8u60 (not 8u51, important!) , working nashorn javascript engine. created own jsobject
extending abstractjsobject
. it's supposed wrap org.json.jsonobject
, make work actual javascript object in script engine. given javaapi
java object put scriptcontext
, resulting object should usable this:
var jsonobject = javaapi.dosomethingthatreturnsajsonobject(); var foo = jsonobject.foo jsonobject.foo = "bar"; delete jsonobject.foo; var message = "json: " + jsonobject;
code
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(); } }
problem
everything works fine except string concatenation. writing like
var message = "json: " + jsonobject;
will result in following exception:
org.json.jsonexception: jsonobject["valueof"] not found. @ org.json.jsonobject.get(jsonobject.java:476) @ my.jsonobjectjavascriptadapter.getmember(jsonobjectjavascriptadapter.java:50) @ jdk.nashorn.api.scripting.defaultvalueimpl.getdefaultvalue(defaultvalueimpl.java:42) @ jdk.nashorn.api.scripting.abstractjsobject.getdefaultvalue(abstractjsobject.java:269) @ jdk.nashorn.api.scripting.abstractjsobject.getdefaultvalue(abstractjsobject.java:285) @ jdk.nashorn.internal.runtime.jstype.toprimitive(jstype.java:512) @ jdk.nashorn.internal.runtime.jstype.toprimitive(jstype.java:480) @ jdk.nashorn.internal.runtime.jstype.toprimitive(jstype.java:462) @ jdk.nashorn.internal.runtime.scriptruntime.add(scriptruntime.java:563) @ jdk.nashorn.internal.scripts.script$recompilation$2$16$configuration.main(src/test/resources/de/ams/inm/workflow/engine/javascript/async/configuration.js:23) @ jdk.nashorn.internal.runtime.scriptfunctiondata.invoke(scriptfunctiondata.java:640) @ jdk.nashorn.internal.runtime.scriptfunction.invoke(scriptfunction.java:228) @ jdk.nashorn.internal.runtime.scriptruntime.apply(scriptruntime.java:393) @ jdk.nashorn.api.scripting.scriptobjectmirror.callmember(scriptobjectmirror.java:199) @ jdk.nashorn.api.scripting.nashornscriptengine.invokeimpl(nashornscriptengine.java:383) @ jdk.nashorn.api.scripting.nashornscriptengine.invokefunction(nashornscriptengine.java:190) [...]
what need make nashorn call tostring()
method message
contain json: {"foo":"bar}
?
solution
it turns out nashorn follows ecma specification letter. important parts the addition operator ( + ) , [[defaultvalue]].
if + operator used objects, objects converted primitives using [[defaultvalue]] function. default [[defaultvalue]] implementation converts objects primitives using either valueof
or tostring
function.
objects may override [[defaultvalue]] function provide custom to-primitive conversion. since java 8u60 possibly in nashorn, overriding abstractjsobject.getdefaultvalue(class)
.
i added following code jsonobjectjavascriptadapter
make string concatenation work excepted:
@override public object getdefaultvalue(class<?> hint) { return tostring(); }
Comments
Post a Comment