从JsArray <javascriptobject>转换为GWT中的List <jsonobject> </jsonobject> </javascriptobject>

时间:2010-06-26 18:44:59

标签: java gwt

在GWT中,我有一个JsArray&lt; JavaScriptObject&gt;在我的代码中。它或多或少是JSON对象的列表,但其类型是JsArray&lt; JavaScriptObject&gt;。它基本上必须采用这种格式,因为我使用JSNI将它作为参数传递给一些外部JavaScript代码。麻烦的是,我也希望Java代码使用这个值。在Java中,我更喜欢处理List&lt; JSONObject&gt;类型的对象。不过,我还没有真正找到转换这两件事的好方法。我能做的最好的是在数组中进行线性遍历以构建我想要的新类型:

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

我非常幸运吗?或者在这两种类型之间有一种很好的快速方法吗?

(返回值的JSONAr也许也可以......但是实现List接口的东西很好。)

5 个答案:

答案 0 :(得分:5)

您无法轻松地将JsArray转换为List接口的任何Java实现的原因是因为JsArray只是一个好的'JavaScript数组'的包装器。这允许对它进行一些非常快速的操作(因为JSON是JS的一部分),但代价是不与“Java”代码的其余部分“兼容”。因此,你必须问问自己速度是否是一个重要因素,如果转换为“Java”列表(当然,内部只是一个JS数组),你会损失多少。

AFAIR,我无法找到任何优雅的解决方案 - 但在我的情况下,我立即使用JsArray对象来创建POJO并进一步传递。

答案 1 :(得分:3)

我们在JsArray周围实现了一个简单的包装器,只支持几种方法。如果您不需要List的所有功能:

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

    ...
}

这是我们发现的最高效,最优雅的解决方案。

答案 2 :(得分:2)

使用@EduardWirch创建包装类的想法,我创建了JsList,它使用和扩展了JsArray的版本,本地处理大部分代码,你可以在JsList得到它。它允许通过JsArrayExtend创建JsList,如下所示:

public class Values extends JavaScriptObject
{
    protected Values (){};
    static public final native JsArrayExtend getValues(String json) /*-{return eval('('+json+')');}-*/;
}

public class Value extends JavaScriptObject
{
    protected Value (){}

    public final native String getName() /*-{return this.name;}-*/;
}

...

JsList<Value> valueList=JsList<Value>(Values.getList(jsonString));

这可以被提供给任何采用List&lt;&gt;的对象。似乎工作正常。我没有彻底测试过,所以如果你发现任何问题请告诉我,我会更新它。

原创我创建了一个JavaScriptObject类型,它使用本机代码就像你在这里看到的列表一样JsList extends JavaScriptObject,但是它打破了GWT类型系统,虽然它适用于Javascript编译,但它不起作用。 / p>

答案 3 :(得分:1)

Turbo GWT Core为它提供了一个优雅的解决方案。在其Js.Collections包中,有JsArrayList,一个包装本机JS数组的List实现。许多合同方法都经过测试并按预期工作。此外,它适用于任何类型的对象,而不仅仅是叠加类型。

您可以像List myList = new JsArrayList(jsArray)一样直接包装JsArray。

Turbo GWT Js.Collections还提供了一个自己的JsArray实现,包含更多方法并支持任何Object。还有一个JsArrayIterator,用于迭代JsArrays。

您可以在https://github.com/growbit/turbogwt-core找到更多信息。

答案 4 :(得分:-2)

我很确定,您尝试过JSONObject.cast()方法。