Как преобразовать массивы Rhino-JavaScript в Java-массивы

StackOverflow https://stackoverflow.com/questions/1433382

  •  07-07-2019
  •  | 
  •  

Вопрос

У меня есть следующее:

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

Как я могу преобразовать результирующий объект типа sun.org.mozilla.javascript.internal.NativeArray в соответствующий массив Java? Может ли кто-нибудь показать мне пример рабочего кода , где это делается? Должно работать для массивов String и Integer. Кроме того, было бы здорово узнать, где искать другие преобразования типов данных между движком rhino и java.

Кстати, я знаю эту страницу , но я действительно ищу пример рабочего кода.

Это было полезно?

Решение

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);
}

Другие советы

Я не уверен, что это был тот случай, когда этот вопрос был задан впервые, но NativeArray реализует интерфейс java.util.List . Поэтому простой способ преобразования в настоящий массив Java:

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

Если Javascript находится под вашим контролем, вы можете выполнить там преобразование, как указано в этот документ . Итак, чтобы адаптировать ваш пример, что-то вроде:

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;

Хотя, если вы не можете изменить Javascript, этот подход не будет работать, и у вас [i] будет [/ i] экземпляр sun.org.mozilla.javascript.internal.NativeArray в качестве переменная результата . В этот момент я думаю, что вам просто нужно разыграть и разобраться с ним напрямую, используя любые открытые методы, которые он выставляет; это, вероятно, не красиво, но я не вижу других вариантов. В частности, я думаю, что единственное, что вы можете гарантировать на хорошем уровне Rhino, это то, что это будет экземпляр Scriptable (и, вероятно, ScriptableObject ), который вам не поможет использовать его как массив.

ответ Кевина выглядит как хороший способ пойти сюда (и похоже на то, что я только что собирался редактировать!: -))

Общее решение с использованием JSON в качестве промежуточного звена данных:

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());
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top