Exobytes is a serialization library for Java 9+ supporting JSON, CBOR and
other formats. Exobytes is designed to give detailed control over the serialized
format and is built around mapping types to Serializer instances either by
manual implementation or via explicit annotations on a type.
This project is licensed under the MIT license,
see the file LICENSE.md for details.
- Low-level streaming input and output
Serializerinterface for encapsulation of how a specific type is written and read- Fine-grained control over serialization
- Annotation-based serializers
- Custom
Serializerimplementation
- Support for injection via
InstanceFactory
<dependency>
<groupId>se.l4.exobytes</groupId>
<artifactId>exobytes</artifactId>
<version>1.0.0</version>
</dependency>The main entry point of the library is the type Serializers. It is recommended
to build a shared Serializers instance for your application and pass it
around:
// Build an instance with all standard serializers and modulesSerializersserializers = Serializers.create()
.build();It's possible to set a custom instance factory to enable injection when using annotation-based serializers:
// Build an instance with all standard serializers and modulesSerializersserializers = Serializers.create()
.withInstanceFactory(instanceFactoryHere)
.build();Serializers are commonly looked up via their class:
Serializer<String> serializer = serializers.get(String.class);This serializer can then be used to write something to a StreamingOutput:
try(StreamingOutputout = StreamingFormat.CBOR.createOutput(outputStream)) {
out.writeObject(serializer, "value to write");
}Or read via StreamingInput:
try(StreamingInputin = StreamingFormat.CBOR.createInput(inputStream)) {
Stringvalue = in.readObject(serializer);
}In Exobytes classes are not serializable by default but instead require an explicit mapping. The most common mapping for types is using annotations and reflection.
Annotate a class with @AnnotationSerialization and the library will resolve
a serializer by looking for @Expose annotations:
@AnnotationSerializationpublicclassEmployee {
@Exposeprivatelongid;
@ExposeprivateStringname;
@Expose@TemporalHints.TimestampprivateLocalDatehired;
}Types can also be made serializable in Exobytes by placing a Use annotation
on them specifying a Serializer or SerializerResolver class that will be
used for the type.
Example of a class that holds a string but skips reflection-based serialization:
@Use(StringHolder.SerializerImpl.class)
publicclassStringHolder {
privatefinalStringvalue;
publicStringHolder(Stringvalue) {
this.value = value;
}
/** * Serializer for StringHolder that reads and writes the class as a single * string. */publicstaticclassSerializerImplimplementsSerializer<StringHolder> {
publicStringHolderread(StreamingInputin) throwsIOException {
// Consume the next token - and make sure it's a valuein.next(Token.VALUE);
// Read the stringStringvalue = in.readString();
// Return the result that should be deserializedreturnnewStringHolder(value);
}
publicvoidwrite(StringHolderobject, StreamingOutputout) throwsIOException {
// Simply write the value of the holderout.writeString(object.value);
}
}
}Most types from java.time are supported with detailed control of the format
via Temporal-annotations.
@Expose@TemporalHints.Precision(ChronoUnit.SECONDS)
@TemporalHints.TimestamppublicInstantcreated;
@Expose@TemporalHints.FormatpublicInstantcreated;
@Expose@TemporalHints.Format(TemporalHints.StandardFormat.ISO_WEEK_DATE)
publicInstantcreated;
@Expose@TemporalHints.CustomFormat("yyyy-MM-dd")
publicZonedDateTimetime;Exobytes supports meta annotations, where you can create an annotation that in turns is annotated with Exobytes annotations. This functionality makes it easy to create standards, such as if you always
@TemporalHints.Precision(ChronoUnit.MILLISECONDS)
@TemporalHints.Timestamppublic @interface StorableTimestamp {
}