我对Nashorn很新,并且在JVM之上编写脚本,想知道我是否可以让我的java代码和javascripts更有效地进行通信。
我正在使用与JS对象一起使用的第三方JS库,在我的java代码中,我将要传递的数据作为Map<String, Object> data
。
因为第三方JS希望使用普通的JS对象,所以我无法按原样传递data
,尽管脚本引擎允许您访问Map,就像它是一个普通的JS对象一样。
我正在使用的脚本在data参数上使用'hasOwnProperty',并且在Java对象上调用时失败。
当我尝试使用Object.prototype.hasOwnProperty.call(data,'myProp')时,它也不起作用并且总是返回'false'。基本问题是Java Object不是javascript对象原型。
我最终做了这样的事情:
Map<String, Object> data;
ObjectMapper mapper = new ObjectMapper();
String rawJSON = mapper.writeValueAsString(data);
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval('third_party_lib.js');
engine.eval('function doSomething(jsonStr) { var jsObj = JSON.parse(jsonStr); return doSomethingElse(jsObj); }');
Object value = ((Invocable) engine).invokeFunction("doSomething", rawJSON);
这可以按预期工作,但所有这些JSON解析来回都很重,感觉可能会有更简单,更快速,更直接的方式来实现它。
那么,有没有更好的方法在Java和Javascript之间传递JSON或者在我的Java代码中创建兼容的JS对象?
我已经看过使用mustache.js进行模板渲染的this指南,但它的功能完全相同。
谢谢!
答案 0 :(得分:6)
Nashorn专门处理java.util.Map对象。 Nashorn允许将Map键视为&#34;属性&#34;。另请参阅https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-SpecialtreatmentofobjectsofspecificJavaclasses
因此,如果您的地图包含&#34; foo&#34;作为键,脚本可以访问mapObj.foo来获取它的值。您评估的脚本是第三方脚本无关紧要。只要该脚本由Nashorn评估,nashorn将专门链接Map属性访问并获得您想要的结果。这种方法避免了不必要的JSON字符串转换和解析往返(正如您自己提到的那样)。