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