Gwt 包含类型化成员的参数化自动bean类型 问题:

Gwt 包含类型化成员的参数化自动bean类型 问题:,gwt,autobean,Gwt,Autobean,是否有任何方法可以使用AutoBean框架反序列化JSON,从而使生成的bean具有影响其一个或多个成员类型的类型参数 背景 带有JSON结果的RPC 我正在使用GWT(RequestBuilder)执行RPC请求。返回的JSON负载的形式如下: { "resultSet": [{...}, {...}, ...], // items requested; say, items 150-160 "totalCount": 15330 // total matc

是否有任何方法可以使用AutoBean框架反序列化JSON,从而使生成的bean具有影响其一个或多个成员类型的类型参数

背景 带有JSON结果的RPC 我正在使用GWT(
RequestBuilder
)执行RPC请求。返回的JSON负载的形式如下:

{
  "resultSet": [{...}, {...}, ...], // items requested; say, items 150-160
  "totalCount": 15330               // total matching items in DB
}
resultSet
中的对象的类型因我调用的特定RPC而异

自动bean接口 我想使用AutoBean反序列化这个JSON。我试图将这个对象表示为:

interface RpcResults<T> {

  List<T> getResultSet();
  void setResultSet(List<T> resultSet);

  int getTotalCount();
  void setTotalCount(int totalCount);

}
基于此堆栈跟踪,我的直觉如下:

  • 类型擦除使
    RpcResults.getResultSet()
    似乎正在返回原始
    列表
  • 自动bean反序列化程序尝试为
    resultSet
    中的每个项创建
    对象
    实例
  • 失败
  • 再问一次
    我是否在AutoBean API中遗漏了一些可以让我轻松做到这一点的东西?如果没有,我是否应该调查一个明显的攻击点?除了我已经在使用的JSONParser和JavaScriptObject之外,还有其他更合理的替代方法吗?

    由于Java类型的擦除,这并不简单。运行时不存在类型
    T
    ,该类型已被擦除为
    Object
    ,以代替任何其他下限。AutoBeanCodex需要类型信息来具体化传入json负载的元素。这种类型信息通常由AutoBean实现提供,但由于
    T
    擦除,它只知道它包含一个
    列表

    如果可以在运行时提供类文本,则可以将getter声明为
    Splittable getResultSet()
    ,并通过调用
    AutoBeanCodex.decode(autoBeanFactory,SomeInterfaceType.class,getResultSet().get(index))
    来具体化列表中的各个元素。通过使用,您可以向AutoBean接口添加一个
    T getResultAs(Class clazz,int index)
    方法。这看起来像:

    @Category(MyCategory.class)
    interface MyFactory extends AutoBeanFactory {
      AutoBean<ResultContainer> resultContainer();
    }
    interface ResultContainer<T> {
      Splittable getResultSet();
      // It's the class literal that makes it work
      T getResultAs(Class<T> clazz, int index);
    }
    class MyCategory {
      public static <T> T getResultAs(Autobean<ResultContainer> bean,
          Class<T> clazz, int index) {
        return AutoBeanCodex.decode(bean.getFactory(), clazz,
          bean.as().getResultSet().get(index)).as();
      }
    }
    
    @Category(MyCategory.class)
    接口MyFactory扩展了AutoBeanFactory{
    自动生成结果容器();
    }
    接口结果容器{
    可拆分的getResultSet();
    //正是类文本使其工作
    T getResultAs(类分类,整数索引);
    }
    类别MyCategory{
    公共静态T getResultAs(自动bean,
    类分类,整数索引){
    返回AutoBeanCodex.decode(bean.getFactory(),clazz,
    bean.as().getResultSet().get(index)).as();
    }
    }
    
    尝试覆盖对象特定接口中的.getResultSet()和.setResultSet()方法:

    interface FooRpcResults extends RpcResults<Foo> {
        @Override
        List<Foo> getResultSet();
        @Override
        void setResultSet(List<Foo> value);
    }
    
    接口FooRpcResults扩展了RpcResults{
    @凌驾
    列出getResultSet();
    @凌驾
    作废setResultSet(列表值);
    }
    
    以下测试适用于我(GWT 2.3.0):

    导入静态org.junit.Assert.assertEquals;
    导入静态org.junit.Assert.assertNotNull;
    导入java.util.ArrayList;
    导入java.util.List;
    导入org.junit.Test;
    导入com.google.web.bindery.autobean.shared.autobean;
    导入com.google.web.bindery.autobean.shared.AutoBeanCodex;
    导入com.google.web.bindery.autobean.shared.AutoBeanFactory;
    导入com.google.web.bindery.autobean.shared.AutoBeanUtils;
    导入com.google.web.bindery.autobean.vm.AutoBeanFactorySource;
    公共类自动测试{
    公共静态接口页{
    int getDataSize();
    列出getPage();
    int getStartIndex();
    void setDataSize(int值);
    无效设置页(列表值);
    无效设置起始索引(int值);
    }
    公共静态接口{
    字符串getName();
    void setName(字符串值);
    }
    公共静态接口ThingFactory扩展了AutoBeanFactory{
    AutoBean createThing();
    AutoBean createThingPage();
    }
    公共静态接口ThingPage扩展页面{
    @凌驾
    列出getPage();
    @凌驾
    无效设置页(列表值);
    }
    @试验
    public void testAutoBean(){
    最终ThingFactory工厂=AutoBeanFactorySource
    .create(ThingFactory.class);
    final Thing thing1=factory.createThing().as();
    内容1.设置名称(“一”);
    final Thing thing2=factory.createThing().as();
    内容2.设置名称(“两个”);
    final List things=new ArrayList();
    事物。添加(事物1);
    事物。添加(事物2);
    最终页面=factory.createThingPage().as();
    第1页:索引(50);
    page.setDataSize(1000);
    page.setPage(事物);
    最终字符串json=AutoBeanCodex.encode(
    getAutoBean(第页)).getPayload();
    最终页面接收页面=AutoBeanCodex.decode(工厂、,
    ThingPage.class,json).as();
    assertEquals(receivedPage.getStartIndex(),page.getStartIndex());
    assertEquals(receivedPage.getDataSize(),page.getDataSize());
    assertNotNull(receivedPage.getPage());
    assertEquals(receivedPage.getPage().size(),page.getPage().size());
    对于(int i=0;i

    删除ThingPage界面中的覆盖将破坏它。

    这种方法对我来说非常有意义。然而,即使使用GWT2.2.0,泛型类型似乎也不能作为分类方法的参数。这意味着不可能将类对象传递给
    getResultAs
    。我已经将您的示例简化为,但GWT编译器会抱怨。如果不能传入类对象,这个相当优雅的解决方案就不起作用了。我认为您的类别中有一个输入错误。您添加了一个方法getResultSet(),而不是将其命名为getResultAs()。您是对的。修正了打字错误,修正了我粘贴的简化案例。我试着更接近你答案中的代码,结果是。但是,这会导致编译错误。(我在
    ResultCategory.getResultAs
    的签名中尝试了
    autobeanbean
    autobeanbean
    ,结果相同。)我仍然是
    interface FooRpcResults extends RpcResults<Foo> {
        @Override
        List<Foo> getResultSet();
        @Override
        void setResultSet(List<Foo> value);
    }
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.junit.Test;
    
    import com.google.web.bindery.autobean.shared.AutoBean;
    import com.google.web.bindery.autobean.shared.AutoBeanCodex;
    import com.google.web.bindery.autobean.shared.AutoBeanFactory;
    import com.google.web.bindery.autobean.shared.AutoBeanUtils;
    import com.google.web.bindery.autobean.vm.AutoBeanFactorySource;
    
    public class AutoBeanTest {
     public static interface Page<T> {
      int getDataSize();
    
      List<T> getPage();
    
      int getStartIndex();
    
      void setDataSize(int value);
    
      void setPage(List<T> value);
    
      void setStartIndex(int value);
     }
    
     public static interface Thing {
      String getName();
    
      void setName(String value);
     }
    
     public static interface ThingFactory extends AutoBeanFactory {
      AutoBean<Thing> createThing();
    
      AutoBean<ThingPage> createThingPage();
     }
    
     public static interface ThingPage extends Page<Thing> {
      @Override
      List<Thing> getPage();
    
      @Override
      void setPage(List<Thing> value);
     }
    
     @Test
     public void testAutoBean() {
      final ThingFactory factory = AutoBeanFactorySource
        .create(ThingFactory.class);
    
      final Thing thing1 = factory.createThing().as();
      thing1.setName("One");
    
      final Thing thing2 = factory.createThing().as();
      thing2.setName("Two");
    
      final List<Thing> things = new ArrayList<Thing>();
      things.add(thing1);
      things.add(thing2);
    
      final Page<Thing> page = factory.createThingPage().as();
      page.setStartIndex(50);
      page.setDataSize(1000);
      page.setPage(things);
    
      final String json = AutoBeanCodex.encode(
        AutoBeanUtils.getAutoBean(page)).getPayload();
    
      final Page<Thing> receivedPage = AutoBeanCodex.decode(factory,
        ThingPage.class, json).as();
    
      assertEquals(receivedPage.getStartIndex(), page.getStartIndex());
      assertEquals(receivedPage.getDataSize(), page.getDataSize());
      assertNotNull(receivedPage.getPage());
      assertEquals(receivedPage.getPage().size(), page.getPage().size());
      for (int i = 0; i < receivedPage.getPage().size(); i++) {
       assertNotNull(receivedPage.getPage().get(i));
       assertEquals(receivedPage.getPage().get(i).getName(), page
         .getPage().get(i).getName());
      }
     }
    }