Как автоматически скопировать значения из Java-бина в объект сообщения protobuf, используя Java-отражение? - PullRequest
4 голосов
/ 29 октября 2010

Как правило, я могу копировать значения между двумя Java-бинами, которые имеют идентичные имена свойств, используя beanutils с java-отражением, например PropertyUtils.setProperty (....)

В protobuf Message мы используем класс построителя сообщенийустановить значение.Это работает, но я бы предпочел использовать отражение для автоматического копирования свойств из bean-компонента в сообщение, так как оба имеют идентичные имена и тип свойств.

Когда я вызываю PropertyUtils.setProperty для объекта построителя (полученного из message.newBuilder()), Я получаю это сообщение.

java.lang.NoSuchMethodException: свойство 'testProp' не имеет метода установки в классе 'class teststuff.TestBeanProtos $ TestBeanMessage $ Builder'

Как мнеавтоматически копировать значения из Java-бина в объект сообщения protobuf (и наоборот), используя java-отражение?

Ответы [ 5 ]

2 голосов
/ 29 октября 2010

Я не хочу отвечать на мой вопрос, но не могу поверить, что я единственный, кто столкнулся с этой проблемой.Документирование решения здесь на случай, если другие люди также начинают работать с protobuf и java.Использование рефлексии позволяет сэкономить на записи десятки методов получения и установки.

Хорошо, мне удалось заставить его работать, используя пример тестового кода, поставляемого с 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 ;
}
2 голосов
/ 29 октября 2010

Я могу быть выключен, но поможет ли protostuff ?Имеет приятную расширенную поддержку для работы с другими форматами данных, типами.И даже если у него нет поддержки прямого преобразования, если вы идете в / из JSON, есть много вариантов для хорошего связывания данных.

1 голос
/ 29 октября 2010

Я не знаю размер вашего проекта, но вы можете попробовать Dozer , картограф, который рекурсивно копирует данные из одного объекта в другой того же типа или между различными сложными типами.Поддерживает неявное и явное отображение.Я использовал его в большом проекте и работал очень хорошо.Это может быть так просто, как

Mapper mapper = new DozerBeanMapper();
DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);
0 голосов
/ 29 марта 2016

У меня та же проблема, решение немного сложнее.

Пожалуйста, используйте взамен MethodUtils.invokeMethod.

, где имя метода - "setXXX".

0 голосов
/ 29 октября 2010

Вы можете бросить все свойства getClass (). GetFields () и сделать копию, используя отражение.Это будет выглядеть как:

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

+ , вероятно, вы можете использовать field.setAccessible (true) invocation.

...