'Get array as result of ScriptEngine.eval()

I'm trying to use javax.script.ScriptEngine to eval() some JS scripts. How can I know if the result after eval() which is of type Object is an array? And if so, how can I cast it?

Right now, to know if the object is of type Number or of type String i use instanceof. And when the result of the script is an array, if I print with System.out.println() the object returned it simply prints [object Array].



Solution 1:[1]

As you noticed, it's not java array but a javascript array, if you print the class of the return object, you probably will find it's "ScriptObjectMirror". I have a work around for this which is toString the array in another your script variable, then get the value of that (see below example). I believe there is a better way to resolve this array issue, waiting the good answer too.

engine.eval("var fruits = [\"Banana\", \"Orange\", \"Apple\", \"Mango\"]; var d = fruits.toString();");
System.out.println(engine.get("fruits").getClass());
System.out.println(engine.get("d").getClass());
System.out.println(engine.get("d"));

Solution 2:[2]

In my case modifying the script to make it return list does the trick:

private String arrayToList() {
    if (javascript.startsWith("[") && javascript.endsWith("]"))
        javascript = "java.util.Arrays.asList(" + javascript + ")";
    return javascript;
}

But of course it handles only the case where array results from using brackets, for example:

["entry1", "entry2", settings.getMainUserEmail(), loginEmail]

Anyway the bottom line is that you need to return a List instead of array. Then you can also use instanceof.

Solution 3:[3]

How can I know if the result after eval() which is of type Object is an array?

Use instanceof:

if(result instanceof Object[]){
    //your code
}

And if so, how can I cast it?

if(result instanceof Object[]){
    Object[] array = (Object[])result;
    for(Object o : array) {
    //your code
    }
}    

Solution 4:[4]

final ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("JavaScript");
scriptEngine.eval("count = ['one', 'two', 'three'];");
scriptEngine.eval("className = count.constructor.name;");

final String className =  (String) scriptEngine.get("className");

switch(className) {

case "Array":
    scriptEngine.eval("json= JSON.stringify(count);");
    final String json =  (String) scriptEngine.get("json");

    final ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    final String[] readValue = mapper.readValue(json, String[].class);
    break;

case "Number":
    ...
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 RedRam
Solution 2
Solution 3 free6om
Solution 4 Oleksandr Potomkin