Codec Module

Codec module allows to encode and decode custom objects in a fast and efficient way.

You can add Codec module to your project by inserting dependency in pom.xml:

<dependency>
    <groupId>io.datakernel</groupId>
    <artifactId>datakernel-codec</artifactId>
    <version>3.0.0-beta1</version>
</dependency>

CodecRegistry allows to easily access pre-defined codecs based on your custom data types. Use create() method to create your CodecRegistry, and with() to setup the codec.

StructuredCodecs contains various implementations of StructuredCodec. StructuredCodec extends StructuredEncoder and StructureDecoder interfaces. It wraps classes, lists, maps and other data structures for encoding/decoding.

Yet, you can create custom codecs. There are several ways to do so:

  1. CodecRegistry has method get, which returns a new StructuredCodec. So, you can first adjust your CodecRegistry and then use it for this purpose.
  2. There are lots of predefined methods which return StructuredCodec.

Examples

Note: To run the examples, you need to clone DataKernel from GitHub:
$ git clone https://github.com/softindex/datakernel
And import it as a Maven project. Before running the examples, build the project.
These examples are located at datakernel -> examples -> core -> codec.

All these examples utilize two utility classes. The first one is a simple POJO Person with three values id, name, dateOfBirth. The second one is Registry, which is needed for encoding/decoding:

public final class Registry {
	public static final CodecRegistry REGISTRY = CodecRegistry.create()
			.with(LocalDate.class, StructuredCodec.of(
					in -> LocalDate.parse(in.readString()),
					(out, item) -> out.writeString(item.toString())))
			.with(Person.class, registry -> object(Person::new,
					"id", Person::getId, INT_CODEC,
					"name", Person::getName, STRING_CODEC,
					"date of birth", Person::getDateOfBirth, registry.get(LocalDate.class)));
}

Let’s now proceed to the examples.

Structured Binary Example

In this example we encode Person John to ByteBuf and then decode him back to Person. To perform such operations, we first need to create a StructuredCodec and then use it for encode and decode operations.

public final class CodecStructuredBinaryExample {
	private static final StructuredCodec<Person> PERSON_CODEC = Registry.REGISTRY.get(Person.class);
	private static final Person john = new Person(121, "John", LocalDate.of(1990, 3, 12));

	private static void encodeDecodeBinary() throws ParseException {
		System.out.println("Person before encoding: " + john);
		ByteBuf byteBuf = BinaryUtils.encode(PERSON_CODEC, john);

		Person decodedPerson = BinaryUtils.decode(PERSON_CODEC, byteBuf);
		System.out.println("Person after encoding: " + decodedPerson);
		System.out.println("Persons are equal? : " + john.equals(decodedPerson));
		System.out.println();
	}

	public static void main(String[] args) throws ParseException {
		encodeDecodeBinary();
	}
}
See this example on GitHub

Structured JSON Example

This example represents how to encode/decode objects to/from JSONs:

public final class CodecStructuredJsonExample {
	private static final StructuredCodec<Person> PERSON_CODEC = Registry.REGISTRY.get(Person.class);
	private static final Person sarah = new Person(124, "Sarah", LocalDate.of(1992, 6, 27));

	private static void encodeDecodeJson() throws ParseException {
		System.out.println("Person before encoding: " + sarah);

		String json = JsonUtils.toJson(PERSON_CODEC, sarah);
		System.out.println("Object as json: " + json);

		Person decodedPerson = JsonUtils.fromJson(PERSON_CODEC, json);
		System.out.println("Person after encoding: " + decodedPerson);
		System.out.println("Persons are equal? : " + sarah.equals(decodedPerson));
		System.out.println();
	}

	public static void main(String[] args) throws ParseException {
		encodeDecodeJson();
	}
}

See this example on GitHub

Structured Collection Example

In this example we perform encode/decode operations on List an Map of two Person objects to/from JSONs:

public final class CodecStructuredCollectionsExample {
	private static final StructuredCodec<Person> PERSON_CODEC = Registry.REGISTRY.get(Person.class);
	private static final Person john = new Person(121, "John", LocalDate.of(1990, 3, 12));
	private static final Person sarah = new Person(124, "Sarah", LocalDate.of(1992, 6, 27));

	private static void encodeDecodeList() throws ParseException {
		List<Person> persons = new ArrayList<>(asList(john, sarah));

		StructuredCodec<List<Person>> listCodec = StructuredCodecs.ofList(PERSON_CODEC);
		System.out.println("Persons before encoding: " + persons);

		String json = JsonUtils.toJson(listCodec, persons);
		System.out.println("List as json: " + json);

		List<Person> decodedPersons = JsonUtils.fromJson(listCodec, json);
		System.out.println("Persons after encoding: " + decodedPersons);
		System.out.println("Persons are equal? : " + persons.equals(decodedPersons));
		System.out.println();
	}

	private static void encodeDecodeMap() throws ParseException {
		Map<Integer, Person> personsMap = new HashMap<>();
		personsMap.put(sarah.getId(), sarah);
		personsMap.put(john.getId(), john);

		StructuredCodec<Map<Integer, Person>> mapCodec = StructuredCodecs.ofMap(INT_CODEC, PERSON_CODEC);
		System.out.println("Map of persons before encoding: " + personsMap);

		String json = JsonUtils.toJson(mapCodec, personsMap);
		System.out.println("Map as json: " + json);

		Map<Integer, Person> decodedPersons = JsonUtils.fromJson(mapCodec, json);
		System.out.println("Map of persons after encoding: " + decodedPersons);
		System.out.println("Maps are equal? : " + personsMap.equals(decodedPersons));
	}

	public static void main(String[] args) throws ParseException {
		encodeDecodeList();
		encodeDecodeMap();
	}
}

See this example on GitHub