1

我需要处理从服务返回的数据,该服务具有比 GXT 文档中提供的示例更复杂的 JSON 结构,到目前为止,我找不到任何说明或示例来说明如何实现这一点。

JSON 包含多个键/值对,但其中一些键/值对是集合。我可以在一次调用中以适当的结构从服务返回给我的所有数据,但似乎没有一种方法可以将数据解析为单独的实体。在我的特殊情况下,我正在尝试配置一个加载器,它将处理其中一个集合,但我还需要来自同一消息的其他键/值对(让加载器进行一次调用然后再调用一次是不行的相同的数据并检索其他键/值对)。有没有办法使用 GXT3 来完成这个?

示例:假设我可以从服务器发出请求,该服务器返回 JSON,其中包含作者姓名以及作者所写书籍的集合。我想在列出书籍的网格上方显示作者的姓名。我只想向服务器发出一个请求,然后让我的视图在一个组件中显示作者,并在网格中显示书籍列表。假设我需要一个加载器而不仅仅是一个商店,因为网格可能需要进行额外的调用(例如,如果它是一个分页网格、livegrid 等)。

示例 JSON:(返回的一条 JSON 消息与作者元素以及书籍元素的集合一起返回 - 我已缩进 JSON 以说明结构)

{ "returnData" : 
  {"author" : "AuthorName"}, 
  {"books" : 
     {"id" : "1", "name" : "Book1"},{"id" : "2", "name" : "Book2"}
  }
}

使用 JsonReader 的示例(有关示例,请参见 javadoc),我可以接收请求并使用 AutoBeans 将链接解析为集合。当我需要在加载器中检索和解析这些内容时,这可以正常工作。但是,如果我这样做,那么其他属性将被忽略。我目前看不到任何方法可以解析同一请求中的其他值,以便它们可以在其他地方使用。我的收集处理示例代码如下:

// this is the root JSON object, the AuthorRecord
public interface AuthorRecord {
  @PropertyName(value="author")
  String getAuthor();
  @PropertyName(value="author")
  void setAuthor(String author);
  @PropertyName(value="books")
  List<Book> getBooks();@
  @PropertyName(value="books")
  void setBooks (List<Book> books);
}

// models the book objects returned
public interface Book {
 @PropertyName(value="id")
 String getId();
 @PropertyName(value="id")
 void setId(String id);
 @PropertyName(value="name")
 String getName();
 @PropertyName(value="name")
 void setName(String name);
}

public interface ReturnData {
  AuthorRootObject getAuthorRoot();
}

public interface LibraryAutoBeanFactory extends AutoBeanFactory {
  AutoBean<ReturnData> authorRecord();
 AutoBean<ListLoadConfig> loadConfig();
}

public class ReturnDataJsonReader extends JsonReader<ListLoadResult<Book>, 
  ReturnData> {
    public ReturnDataJsonReader(AutoBeanFactory factory, 
      Class<ReturnData> rootBeanType) {
        super(factory, rootBeanType);
    }

    @Override
    protected ListLoadResultBean<Book> createReturnData(Object loadConfig, 
      ReturnData incomingData) {
        return new ListLoadResultBean<Book>(incomingData.getBooks());
    }
}
4

1 回答 1

1

我遇到的问题是我需要一个视图,其中包含一个列出书籍的网格(分页网格等),同时让作者的名字位于网格上方。我想通过对服务器的一个请求来获取所有这些信息(或至少是结果的第一页),因为 JSON 消息包含我完成此操作所需的所有信息。问题是加载器发出请求并接收响应,它期望它将使用的读取器将处理一个集合。就我而言,我需要加载器来处理书籍的集合,但还要填充另一个数据字段。我找到的解决方案是创建一个任意集合以传递给加载器,然后实现我自己的加载处理程序以根据需要处理返回对象。

1.返回的JSON实际上只是ReturnData类型的一个对象。扩展的 JsonReader 可以使用 AutoBeans 来处理这个,但是如果读取器用于加载器,它需要返回一个集合。因此,重写 createReturnData() 方法以返回一个对象的集合。

public class ReturnDataJsonReader extends JsonReader<ListLoadResult<AuthorRecord>, 
  ReturnData> {

  public ReturnDataJsonReader(AutoBeanFactory factory, Class<ReturnData> rootBeanType) 
  {      
    super(factory, rootBeanType);   
  }    

  @Override   
  protected ListLoadResultBean<AuthorRecord> createReturnData(Object loadConfig,
      ReturnData incomingData) {       

    List<AuthorRecord> authorDataCollection = new ArrayList<AuthorRecord>();
    authorDataCollection.add(incomingData);
    return authorDataCollection;    
  }
}

2. 示例中使用的 LoadHandler 将 ListStore 作为输入,并使用加载程序的结果填充它。由于返回对象不是我们想要填充加载器的对象,并且由于我们需要填充视图上的另一个属性,因此创建您自己的 LoadHandler 以将所需的对象作为输入并填充它们:

查看类示例:

public class ExampleViewClass {
 // truncating most of the code in here for brevity
 // note some of the objects referenced here reference objects in the question
 private String authorName;
 private ListStore<Book> bookList;

 // IMPORTANT - create your own LoadHandler
 private class LibraryLoadResultistStoreBinding<C, M, D extends
    ListLoadResult<AuthorRecord>> implements LoadHandler<ListLoadConfig, 
    ListLoadResult<AuthorRecord>> {

      private final ListStore<Book> bookStore;
      private final String authorName;

      public LibraryLoadResultistStoreBinding(ListStore<Book> books, String author) {
          this.bookStore = books;
          this.authorName = author;
      }

      @Override
      public void onLoad(LoadEvent<ListLoadConfig, ListLoadResult<AuthorRecord> event) 
      {
        // the response object
        AuthorRecord response = event.getLoadResult().getData().get(0);  
        bookStore.replaceAll(response.getBooks());
        author = response.getAuthor();
      }
   }

   // example uses an HttpProxy but that's not required
   public void populateView() {
     LibraryAutoBeanFactory factory = GWT.create(LibraryAutoBeanFactory.class);
     ReturnDataJsonReader reader = new ReturnDataJsonReader(factory, ReturnData.class);
     String path = "http://path.to.resource/getinfo";
     RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
     HttpProxy<ListLoadConfig> proxy = new HttpProxy<ListLoadConfig>(builder);

     final ListLoader<ListLoadConfig, ListLoadResult<AuthorRecord>> loader = new       
       ListLoader<ListLoadConfig, ListLoadResult<AuthorRecord>> (proxy, reader);

     loader.useLoadConfig(ReturnDataAutoBeanFactory.instance.loadConfig().as();

     loader.addLoadHandler(new LibraryLoadResultistStoreBinding<ListLoadConfig, 
       AuthorRecord, ListLoadResult<AuthorRecord>>(bookList, authorName);  
     // pass in the objects to be populated

     loader.load();  // fire the loader
   }
于 2012-12-31T14:37:17.997 回答