2009-09-16 18 views
17

Tengo el siguiente:Cómo convertir matrices de JavaScript Rhino-a-Java Arrays

ScriptEngineManager mgr = new ScriptEngineManager(); 
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript"); 
jsEngine.eval("function getArray() {return [1,2,3,4,5];};"); 
Object result = jsEngine.eval("getArray();"); 

¿Cómo puedo convertir el objeto de resultado que es de tipo sun.org.mozilla.javascript.internal.NativeArray a una correspondiente matriz de Java? ¿Puede alguien mostrarme una muestra del código de trabajo donde se hace esto? Debería funcionar para arrays String y Integer. Además, sería genial saber dónde buscar otras conversiones de tipo de datos entre el motor de rinoceronte y Java.

Btw, i know this page pero realmente estoy buscando un ejemplo de código de trabajo.

Respuesta

22
NativeArray arr = (NativeArray) result; 
Object [] array = new Object[(int) arr.getLength()]; 
for (Object o : arr.getIds()) { 
    int index = (Integer) o; 
    array[index] = arr.get(index, null); 
} 
+0

gracias por ayudar a un chico tonto ;-) deseo todas las respuestas que serían preciso, corto y funcionando! – Chris

+0

Me pregunto por qué no puedes convertir todo el conjunto getIds en Integer []. Obtengo una ClassCastException. Oh, bueno – TheLQ

7

Si el Javascript está bajo su control, puede hacer la transformación allí, según this document. Así que para adaptar su ejemplo, algo como:

ScriptEngineManager mgr = new ScriptEngineManager(); 
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript"); 
jsEngine.eval("function getArray() {return [1,2,3,4,5];};"); 
String convertFuncSrc = 
    "function convertArray(type, arr) {" 
    + " var jArr = java.lang.reflect.Array.newInstance(type, arr.length);" 
    + " for (var i = 0; i < arr.length; i++) { " 
    + " jArr[i] = arr[i];" 
    + " }" 
    + " return jArr;" 
    + "};"; 
jsEngine.eval(convertFuncSrc); 
Object result = jsEngine.eval("convertArray(java.lang.Integer.TYPE, getArray());"); 
int[] javaArray = (int[])result; 

Aunque, si no se puede cambiar el Javascript este enfoque no funcionará, y usted [i] será [/ i] tienen una instancia de sun.org .mozilla.javascript.internal.NativeArray como su variable result. En ese punto, creo que solo necesita lanzar y tratar con él directamente, utilizando los métodos públicos que expone; probablemente no sea bonita, pero no veo ninguna otra opción. En particular, creo que lo único que puede garantizar al buen nivel de Rhino es que será una instancia de Scriptable (y probablemente ScriptableObject), lo que no le ayuda a usarlo como una matriz.

Kevin's answer parece una buena manera de ir aquí (y es similar a lo que estaba a punto de editar en! :-))

8

no estoy seguro de si era el caso cuando este La pregunta se realizó primero, pero NativeArray implementa la interfaz java.util.List. Por tanto, una forma sencilla de convertir en un verdadero arsenal de Java es:

Object[] array = ((List<?>) result).toArray(); 
+0

jdk1.6.0_45 dice que sun.org.mozilla.javascript.internal.NativeArray no puede ser lanzado a java.util.List – pal

+0

@pal NativeArray definitivamente implementa List en versiones más recientes de Rhino, pero no estoy seguro de cuándo fue el primero en el caso Ver [aquí] (http://javadox.com/org.mozilla/rhino/1.7R3/org/mozilla/javascript/NativeArray.html). –

+1

Por cierto, Nashorn (el motor de JavaScript incluido con Java 8) lamentablemente devuelve objetos de una clase (ScriptObjectMirror) que implementa Map en lugar de List. Si quiere que su código funcione tanto en Java 7 como en 8+, tendrá que hacer una instancia de verificación. –

0

Solución general usando JASON como datos intermedia:

Object result = jsEngine.eval("JSON.stringify(getArray())");  
JsonReader jsonReader = Json.createReader(new StringReader(result.toString())); 
JsonArray jsonArray = jsonReader.readArray(); 
jsonReader.close(); 
int[] numbers = new int[jsonArray.size()]; 
int index = 0; 
for(JsonValue value : jsonArray){ 
    numbers[index++] = Integer.parseInt(value.toString()); 
} 
Cuestiones relacionadas