【问题标题】:Converting from JsArray<JavaScriptObject> to List<JSONObject> in GWT在 GWT 中从 JsArray<JavaScriptObject> 转换为 List<JSONObject>
【发布时间】:2010-06-26 18:44:59
【问题描述】:

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

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

我真的很倒霉吗?或者有没有一种快速的方法可以在这两种类型之间进行转换?

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

【问题讨论】:

    标签: java gwt


    【解决方案1】:

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

    AFAIR,我还没有找到任何优雅的解决方案来解决这种情况 - 但就我而言,我立即使用 JsArray 对象来创建 POJO 并进一步传递它们。

    【讨论】:

      【解决方案2】:

      我们围绕 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);
          }
      
          ...
      }
      

      这是我们找到的最高效、最优雅的解决方案。

      【讨论】:

      • 你能分享完整的实现吗?谢谢!
      • 类的其余部分与我发布的截图几乎相同。这个答案太长了。
      【解决方案3】:

      根据@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 并且似乎工作正常的对象。我没有彻底测试过,如果你发现任何问题,请告诉我,我会更新它。

      原来我创建了一个 JavaScriptObject 类型,它使用本机代码来充当列表,您可以在此处看到 JsList extends JavaScriptObject,但是它破坏了 GWT 类型系统,虽然它适用于 Javascript 编译,但它在其他情况下不起作用。

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-25
          • 1970-01-01
          • 1970-01-01
          • 2019-10-07
          • 1970-01-01
          • 2018-04-24
          相关资源
          最近更新 更多