ASN.1 — стандарт описания протоколов передачи данных. Вот уже 8 лет не дает покоя тот факт, что существуют либо слабые попытки его использовать, практически не прибегая к его полному функционалу, либо же это монстры за большие деньги, используемые отнюдь не рядовым Васей.
Причем и те и другие наследуют одни и те же черты — неудобство, перегруженность дополнительными действиями и генерацией совсем бесполезных заглушек.
На хабре появлялось уже достаточно много статей с описанием всех прелестей ASN.1, рекомендую почитать их.
Вашему вниманию предлагаю альфа-версию библиотеки, позволяющей в стиле hibernate или jackson-databind сохранить ваши данные в бинарном виде. Пока поддерживаются только нотации BER(DER).
Примеры использования
ASN.1 S уже сейчас позволяет сериализовать классы с примитивами (и их упакованной версией):
@Sequence( name = "Message", tagNumber = 2 ) public class Message { @Property( optional = true ) private Integer id; @Property( typeName = "GeneralizedTime" ) private Instant stamp; @Property private String text; @Constructor public Message( @ConstructorParam( value = "manager", global = true ) ObjectManager manager, @ConstructorParam( "id" ) Integer id, @ConstructorParam( "stamp" ) Instant stamp, @ConstructorParam( "userId" ) int userId, @ConstructorParam( "text" ) String text ) { this.id = id; this.stamp = stamp; user = manager.getUser( userId ); this.text = text; } //... private User user; @Property public int getUserId() { return user.getId(); }
Разумеется задавать поля в конструкторе не обязательно. Достаточно сделать все поля доступными для записи через сеттеры и не забыть про конструктор по умолчанию (jackson вас тоже по рукам бить будет):
@Sequence( name = "User" ) public class User { @Property private int id; @Property private String name; @Property private String accessKey; public User(){ } public User( int id, String name, String accessKey ) { ... } public int getId(){return id;} public void setId( int id ){this.id = id;} public String getName(){return name;} public void setName( String name ){this.name = name;} public String getAccessKey() { return accessKey; } public void setAccessKey( String accessKey ) { this.accessKey = accessKey; }
В данный момент наличие аннотации обязательно, но ничто не мешает сделать вариант полностью аналогичный jackson — данные можно сериализовать как есть, без всяких метаданных, написан��ых вами, основываясь на reflection. Сейчас этого нет в целях отладки — жесткие системы всегда проще отладить.
Так же поддерживаются массивы (тип указывается, что бы библиотека не генерировала свое — T-Java-Bind-org-asn1s-databind-tests-persons-Person-Array):
@Property( optional = true, typeName = "Person-Array" ) private Person[] family;
И списки, если класс элемента один:
@Property( typeName = "NoteList" ) private List<Note> notes;
В будущем можно будет задавать набор классов, которые могут появится в коллекции (в духе
@ItemClass({Note.class, Book.class, Paper.class}) ). Все необходимое в библиотеке есть, а ASN.1 поддерживает несколько механизмов реализации (CHOICE, INSTANCE OF, можно даже поиграться с SEQUENCE и SET, используя необязательные поля).
И наконец пример в сериализованном виде:

Быстродействие
Серьезных исследований не проводилось, но в сравнении с jackson ASN.1 S работает на порядок хуже.
PersonsTest.testPersonsJsonRead: [measured 100000 out of 110000 rounds, threads: 1 (sequential)] ... time.total: 0.33, time.warmup: 0.10, time.bench: 0.22 PersonsTest.testPersonsRead: [measured 100000 out of 110000 rounds, threads: 1 (sequential)] ... time.total: 1.05, time.warmup: 0.26, time.bench: 0.79 PersonsTest.testPersonsJsonWrite: [measured 100000 out of 110000 rounds, threads: 1 (sequential)] ... time.total: 0.21, time.warmup: 0.05, time.bench: 0.16 PersonsTest.testPersonsWrite: [measured 100000 out of 110000 rounds, threads: 1 (sequential)] ... time.total: 1.17, time.warmup: 0.22, time.bench: 0.95
Использование NIO позволит повысить быстродействие, в данный момент буферизация делается через стек из ByteArrayOutputStream — самый простой способ, приводящий к огромному числу операций копирования и выделения памяти.
Заключение
Представлена библиотека с открытым исходными кодом под лицензией MIT. Несмотря на версию альфа — уже можно использовать для простых случаев.
