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