Java: Returning an object from ScriptEngine javascript

限于喜欢 提交于 2019-12-03 10:20:02

问题


I'm trying to evaluate javascript in Java by using the ScriptEngine class. Here is a short example of what I am trying to do:

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;

public class Test {
    public static void main(String[] args) {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); //Creates a ScriptEngine
        Object obj = engine.eval("var obj = { value: 1 }; return obj; "); // Evals the creation of a simple object
        System.out.println(obj.value); // I get an invalid token error when trying to print a property of the object
    }
}

I'm pretty sure that this should work... but I'm stumped, and I'll take any help I can get.


回答1:


Note: The following is for Java 8, using the Nashorn engine.

First, to make the code compile, remove the .value from the println() statement. obj is declared to be type Object, and Object doesn't have a value field.

Once you do that, you get the following exception when running the code:

Exception in thread "main" javax.script.ScriptException: <eval>:1:25 Invalid return statement
var obj = { value: 1 };  return obj; 
                         ^ in <eval> at line number 1 at column number 25

That is because you don't have a function, so you cannot call return. The return value of the script is the value of the last expression, so just say obj.

Now it will run and print [object Object]. To see what type of object you got back, change to println(obj.getClass().getName()). That will print jdk.nashorn.api.scripting.ScriptObjectMirror. I've linked to the javadoc for your convenience.

ScriptObjectMirror implements Bindings which in turn implements Map<String, Object>, so you can call get("value").

Working code is:

import javax.script.*;

public class Test {
    public static void main(String[] args) throws ScriptException {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
        Bindings obj = (Bindings)engine.eval("var obj = { value: 1 };  obj; ");
        Integer value = (Integer)obj.get("value");
        System.out.println(value); // prints: 1
    }
}

UPDATE

The whole point was to create an object with functions, is that possible with this engine? There isn't a Function object.

Example for how to do that:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class Test {
    public static void main(String[] args) throws Exception {
        String script = "var f = {\n" +
                        "  value: 0,\n" +
                        "  add: function(n) {\n" +
                        "    this.value += n;\n" +
                        "    return this.value;\n" +
                        "  }\n" +
                        "};\n" +
                        "f; // return object to Java\n";
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
        ScriptObjectMirror obj = (ScriptObjectMirror)engine.eval(script);
        System.out.println("obj.value = " + obj.getMember("value"));
        System.out.println("obj.add(5): " + obj.callMember("add", 5));
        System.out.println("obj.add(-3): " + obj.callMember("add", -3));
        System.out.println("obj.value = " + obj.getMember("value"));
    }
}

OUTPUT

obj.value = 0
obj.add(5): 5.0
obj.add(-3): 2.0
obj.value = 2.0


来源:https://stackoverflow.com/questions/38034497/java-returning-an-object-from-scriptengine-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!