📜 ⬆️ ⬇️

Automatic serialization of Java objects in ASN.1

ASN.1 is a standard for describing data transfer protocols. For the past 8 years, the fact that there are either weak attempts to use it, almost without resorting to its full functionality, or else monsters for big money, used by ordinary Vasya, has been haunting.
And both of them inherit the same features - inconvenience, overloading with additional actions and generation of completely useless stubs.
On Habré already appeared a lot of articles describing all the charms of ASN.1, I recommend reading them.


I would like to bring to your attention an alpha version of the library , which allows you to save your data in binary form in the hibernate or jackson-databind style. So far, only BER (DER) notation is supported.


Examples of using


ASN.1 S already allows you to serialize classes with primitives (and their packaged version):


@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(); } 

Of course, it is not necessary to set fields in the constructor. It is enough to make all the fields available for writing through setters and not forget about the default constructor (jackson will beat you too):


 @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; } 

At the moment, the presence of annotations is necessary, but nothing prevents to make a variant completely analogous to jackson - data can be serialized as it is, without any metadata written by you, based on reflection. Now this is not for debugging purposes - hard systems are always easier to debug.


Arrays are also supported (the type indicates that the library does not generate its own - T-Java-Bind-org-asn1s-databind-tests-persons-Person-Array):


  @Property( optional = true, typeName = "Person-Array" ) private Person[] family; 

And the lists, if the class of the element is one:


  @Property( typeName = "NoteList" ) private List<Note> notes; 

In the future, it will be possible to set a set of classes that may appear in the collection (in the spirit of
@ItemClass({Note.class, Book.class, Paper.class}) ) . There is everything you need in the library, and ASN.1 supports several implementation mechanisms (CHOICE, INSTANCE OF, you can even play around with SEQUENCE and SET, using optional fields).


Finally, an example in serialized form:
image


Speed ​​performance


Serious studies have not been conducted, but compared to jackson ASN.1 S works much worse.


 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 

Using NIO will improve performance, currently buffering is done through a stack of ByteArrayOutputStream - the easiest way, resulting in a huge number of copy and memory allocations.


Conclusion


Introduced an open source library under the MIT license. Despite the alpha version - it can already be used for simple cases.


')

Source: https://habr.com/ru/post/333502/


All Articles