tags:

views:

44

answers:

3

In GWT, I have a JsArray<JavaScriptObject> in my code. It's more or less a list of JSON objects, but its type is JsArray<JavaScriptObject>. It basically has to be in this format, because I pass it as a parameter to some external JavaScript code using JSNI. Trouble is, I also want this value to be used by Java code. In Java, I'd prefer to deal with an object of type List<JSONObject>. I haven't really found a good way to convert between these two things, though. The best I've been able to do is a linear walk through the array to build the new type I want:

  public List<JSONObject> getData() {
   LinkedList<JSONObject> list = new LinkedList<JSONObject>();
   for (int i = 0; i < data.length(); ++i) {
    list.add(new JSONObject(data.get(i)));
   }
   return list;
  }

Am I horribly out of luck? Or is there a nice fast way to get between these two types?

(Returning a JSONArray of values would perhaps be OK as well... but something that implements the List interface is nice).

A: 

I am quite sure, you tried the JSONObject.cast() method.

iftee
A: 

The reason why you can't easily cast JsArray to any Java implementation of the List interface is because JsArray is just a wrapper around a good ol' JavaScript array. This allows for some very quick operations on it (since JSON is part of JS), but at the cost of not being "compatible" with the rest of the "Java" code. So you have to ask yourself if speed is an important factor and how much will you lose if you convert to a "Java" list (which, of course, internally will be just a JS array).

AFAIR, I haven't been able to find any elegant solution to this situation - but in my case I used the JsArray objects right away to create POJOs and pass those further.

Igor Klimer
A: 

We implemented a simple wrapper around JsArraysupporting just few methods. If you don't need all the List's functionality:

public class JsArrayList<T> implements List<T> {

    private final JsArray<? extends T>  array;

    public JsArrayList(final JsArray<? extends T> array) {
        this.array = array;
    }

    public boolean add(final T e) {
        throw new RuntimeException("Not implemented.");
    }

    public boolean isEmpty() {
        return this.size() == 0;
    }

    public Iterator<T> iterator() {
        if (array == null) {
        return new EmptyIterator<T>();
    } else {
        return new JsArrayIterator<T>(array);
    }
    }

    public int size() {
        if (array == null) return 0;
        return array.length();
    }

    public T get(final int index) {
        if (array == null) { throw new IndexOutOfBoundsException("array is emtpy"); }
        return array.get(index);
    }

    ...
}

This is the most performant and elegant solution we found.

Eduard Wirch