Библиотека для преобразования объектов вашей доменной модели в Google Protobuf сообщения и наоборот.

Подключение

Вы можете добавить эту библиотеку в качестве зависимости для вашего Maven или Gradle проекта через JitPack.

Использование

Доменная модель классов, которые должны быть преобразованы в Protobuf сообщения, должны удовлетворять условиям:
  • Класс должен быть отмечен @ProtoClass аннотацией, которая указывает на соответствующий класс Protobuf сообщений.
  • Поля класса должен быть отмечены @ProtoField аннотацией. Эти поля должны иметь геттеры и сеттеры.

Например:
                @ProtoClass(ProtobufUser.class)
                public class User {

                @ProtoField
                private String name;

                @ProtoField
                private String password;

                // getters and setters for 'name' and 'password' fields
                ...
            }

Код для преобразования экземпляра объекта User в соответствующее Protobuf сообщение:
                User userDomain = new User();
                ...
                ProtobufUser userProto = Converter.create().toProtobuf(ProtobufUser.class, userDomain);
            

Код для обратного преобразования:
        User userDomain = Converter.create().toDomain(User.class, userProto);
Преобразование списка объектов происходит аналогично.

@ProtoClass

Аттрибуты аннотации:
  • value - обязательный. Содержит ссылки на Protobuf класс сообщений.
  • mapper - необязательный. Содержит ссылку на класс, который выполняет отображение значения поля между доменным и Protobuf объектом во время преобразования. Значение по умолчанию - DefaultMapperImpl.class

Атрибут mapper полезн, когда класс доменной модели и Protobuf класс сообщений имеет различную структуру. В таком случае вы должны создать собственную реализацию Mapper и указать его в качестве значения mapper атрибута.
Если тип доменого объекта поля является сложным (отмечен @ProtoClass) protobuf-converter преобразует значение этого поля в соответствующее Protobuf сообщение (DefaultMapperImpl.class должен быть указан в качестве значения mapper атрибута)

@ProtoField

Аттрибуты аннотации:
  • name - необязательный. Связное имя protobuf поля.
  • converter - необязательный. Содержит ссылку на класс, который выполняет преобразование значения поля. Значение по умолчанию - DefaultConverterImpl.class
  • nullValue - необязательный. Содержит ссылку на класс, который проверяет protobuf поле объекта для допустимость null значений. Значение по умолчанию - DefaultNullValueInspectorImpl.class
  • defaultValue - необязательный. Содержит ссылку на класс, который инициализирует поле доменного объекта, если связанные с protobuf поля не инициализированны. Значение по умолчанию - SimpleDefaultValueImpl.class

Используйте аттрибут name, когда имя поля доменного класса отличается от имени, указанного в файле * .proto.
атрибут converter является полезным, когда тип поля доменого класса отличается от типа поля protobuf сообщения. Пример: значение даты в классе домена хранится в java.util.Date и protobuf сообщение использует int64 (java.lang.Long). Для преобразования данных поля необходимо указать DateLongConverterImpl.class в качестве значения converter атрибута. Вы можете создать собственный преобразователь типа поля, если вы реализуете интерфейс TypeConverter.

Fields Ignore

В случае, если вам нужно предотвратить конвертирование некоторых значений доменных полей в значения полей protobuf сообщений используйте FieldsIgnore.class. Пример: когда сервер генерирует ответ на запрос данных пользователем, посланный клиентским приложением поле password User.class не должно быть преобразованно в поле ProtobufUser.class. Вам нужно добавить в список игнорирования password поле:
User userDomain = new User();
...
FieldsIgnore ignoredFiedls = new FieldsIgnore().add(User.class, \"password\");
Configuration configuration = Configuration.builder().addIgnoredFields(ignoredFiedls).build();
ProtobufUser userProto = Converter.create(configuration).toProtobuf(ProtobufUser.class, userDomain);
FieldsIgnore.class позволяет игнорировать поля согласно типу, также легко как и одно поле.
Пример: можно игнорировать все поля типа java.lang.String:
User userDomain = new User();
...
FieldsIgnore ignoredFiedls = new FieldsIgnore().add(String.class);
Configuration configuration = Configuration.builder().addIgnoredFields(ignoredFiedls).build();
ProtobufUser userProto = Converter.create(configuration).toProtobuf(ProtobufUser.class, userDomain);

Обфускация

Основные Proguard опции:
-keep interface net.badata.protobuf.converter.** { *; }

-keep public class * implements net.badata.protobuf.converter.mapping.Mapper {
     public <init>();
}

-keep public class * implements net.badata.protobuf.converter.type.TypeConverter {
     public <init>();
}

-keep public class * implements net.badata.protobuf.converter.inspection.DefaultValue {
     public <init>();
}

-keep public class * implements net.badata.protobuf.converter.inspection.NullValueInspector {
     public <init>();
}
Оставьте нетронутыми ваши доменные объекты (замените your.package.name именем пакета, в котором хранятся ваши объекты доменной модели):
-keepclassmembers @net.badata.protobuf.converter.annotation.ProtoClass public class your.package.name.** {
     @net.badata.protobuf.converter.annotation.ProtoField <fields>;
     public <init>();
     public void set*(***);
     public boolean is*();
     public  *** get*();
}

Примеры

Возможности protobuf-converter демонстрируется проект, расположенный в папке example.
Собрать example проект:
gradle assemble
Запустить сервер:
java -jar example.jar \"server\"
Запустить клиент:
java -jar example.jar

Лицензия

GNU General Public License v3.0

GitHub Activity Stream