如何使用java反射自动将值从java bean复制到protobuf消息对象?

时间:2010-10-29 16:05:22

标签: java reflection protocol-buffers

通常,我可以使用带有java反射的beanutils在两个具有相同属性名称的java bean之间复制值,例如PropertyUtils.setProperty(....)

在protobuf Message中,我们使用消息构建器类来设置值。这有效,但我宁愿使用反射来自动地将属性从bean复制到消息,因为它们具有相同的属性名称和类型。

当我在构建器对象上调用PropertyUtils.setProperty时(从message.newBuilder()获取),我收到此消息。

java.lang.NoSuchMethodException:属性'testProp'在类'class teststuff.TestBeanProtos $ TestBeanMessage $ Builder'

中没有setter方法

如何使用java反射自动将值从java bean复制到protobuf消息对象(反之亦然)?

5 个答案:

答案 0 :(得分:2)

我讨厌回答我的问题,但我不能相信我是唯一一个遇到这个问题的人。记录解决方案,以防其他人也开始使用protobuf和java。使用反射可以节省数十个getter和setter。

好的,我设法使用protobuf附带的一些示例测试代码来使用它。这是一个非常简单的用例;通常情况下,消息会更加复杂。此代码不处理嵌套消息或重复消息。

public static void setMessageBuilder(com.google.protobuf.GeneratedMessage.Builder message,Descriptors.Descriptor descriptor,Object srcObject) throws Exception {
    String cname = srcObject.getClass().getName();
    /*BeanMapper.getSimpleProperties -- this is a warpper method that gets the list of property names*/ 
    List<String> simpleProps = BeanMapper.getSimpleProperties(srcObject.getClass());

    Map map = new HashMap();
    for (String pName : simpleProps) {
        System.out.println(" processing property "+ pName);
        Object value= PropertyUtils.getProperty(srcObject, pName);
        if(value==null) continue;

        Descriptors.FieldDescriptor fd=descriptor.findFieldByName(pName) ;

        System.out.println(" property "+  pName+" , found fd :"+ (fd==null ? "nul":"ok"));
         message.setField(fd, value);
         System.out.println(" property "+  pName+"  set ok,");

    }
    return ;
}

答案 1 :(得分:2)

我可能会离开,但protostuff会帮忙吗?它具有很好的扩展支持,可以使用其他数据格式,类型。即使它没有直接转换支持,如果你去往/来自JSON,有很多选择可以进行良好的数据绑定。

答案 2 :(得分:1)

我不知道您项目的大小,但您可能想要尝试Dozer,这是一个映射器,它将数据从一个对象递归复制到另一个对象或同一类型之间或不同复杂类型之间。也支持隐式和显式映射。我在一个大项目中使用它并且工作得非常好。它可以像

一样简单
Mapper mapper = new DozerBeanMapper();
DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);

答案 3 :(得分:0)

你可以抛出所有属性 getClass()。getFields()并使用反射进行复制。它会像smt一样:

for(Field f : to.getClass().getFields()){
    f.set(to, from.getClass().getField(f.getName()).get(from));
}

+ 可能您可能会使用 field.setAccessible(true)调用。

答案 4 :(得分:0)

我遇到了同样的问题,解决方案有点棘手。

请使用 MethodUtils.invokeMethod 代替。

其中方法名称为“setXXX”。