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

Popular posts from this blog

c# - Binding a comma separated list to a List<int> in asp.net web api -

Delphi 7 and decode UTF-8 base64 -

html - Is there any way to exclude a single element from the style? (Bootstrap) -