最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Java: Returning an object from ScriptEngine javascript - Stack Overflow

programmeradmin0浏览0评论

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.

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.

Share Improve this question edited Jun 26, 2016 at 17:37 bcsb1001 2,9073 gold badges25 silver badges37 bronze badges asked Jun 26, 2016 at 1:38 hjk321hjk321 4371 gold badge5 silver badges10 bronze badges 5
  • Does it work if you drop return obj;? Return statements should be in functions, but then I don't know how that class evaluates the JS code. – user1106925 Commented Jun 26, 2016 at 1:44
  • 1 I'm not really sure how it works either; I just saw a couple of examples and the documentation. I get the same error when ommiting. – hjk321 Commented Jun 26, 2016 at 1:46
  • Probably because of the var statement, which won't return the object itself. Just the object wrapped in parentheses may work. The parens will be necessary for a valid program. – user1106925 Commented Jun 26, 2016 at 2:00
  • @squint OP has a compile error, (the "invalid token error" mentioned in the comment to the println() statement), not a runtime error. See my answer for why. – Andreas Commented Jun 26, 2016 at 2:03
  • @Andreas: I know, see my first comment. I'm just saying that neither var obj = { value: 1 }; nor { value: 1 }; would likely work because neither statement alone produces an object, while ({value: 1}) would. – user1106925 Commented Jun 26, 2016 at 2:14
Add a comment  | 

1 Answer 1

Reset to default 14

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
发布评论

评论列表(0)

  1. 暂无评论