Core Java

Serialization with FlatBuffers in Java

FlatBuffers in Java facilitates high-speed data serialization/deserialization, eliminating parsing overhead. Developed by Google, it offers a schema-less, memory-efficient solution for cross-platform data exchange. Java developers can harness its direct memory access for optimal performance and minimal memory footprint, enhancing application speed, scalability, and interoperability. Let us delve into understanding the Java FlatBuffers serialization.

1. Understanding Serialization and FlatBuffers in Java

In Java programming, serialization refers to the process of converting objects into a stream of bytes. This stream of bytes can then be stored in a file, sent over a network, or saved in a database. Serialization is essential for data persistence and communication between different systems.

1.1 Serialization in Java

Java provides built-in support for serialization through the Serializable interface. Classes that implement this interface can be serialized and deserialized using Java’s ObjectOutputStream and ObjectInputStream classes. Additionally, Java offers an Externalizable interface for more fine-grained control over the serialization process.

1.2 FlatBuffers in Java

FlatBuffers is an efficient cross-platform serialization library developed by Google. Unlike traditional serialization methods, FlatBuffers do not require parsing. Instead, they provide direct access to serialized data, resulting in faster serialization and deserialization. In Java, FlatBuffers are implemented through a code generator that produces Java classes based on a schema definition. These generated classes enable developers to easily serialize and deserialize data without the need for manual parsing or reflection. This results in high-performance data processing with minimal overhead.

1.2.1 Benefits of Using FlatBuffers

  • Efficient Memory Usage: FlatBuffers use memory more efficiently compared to other serialization formats.
  • High-Speed Serialization and Deserialization: Direct access to serialized data leads to faster processing.
  • Support for Schema Evolution: FlatBuffers allow for schema changes without breaking backward compatibility.
  • Platform Independence: Serialized data can be shared across different platforms and programming languages.

2. Code Example

Consider a simple example where we have a schema definition for a person with fields like name, age, and list of hobbies. We’ll create instances of this person object, serialize them using FlatBuffers, and then deserialize them back.

2.1 Maven Dependency

You can use the provided Maven dependency to include FlatBuffers in the project.

<!-- https://mvnrepository.com/artifact/com.google.flatbuffers/flatbuffers-java -->
<dependency>
    <groupId>com.google.flatbuffers</groupId>
    <artifactId>flatbuffers-java</artifactId>
    <version>24.3.25</version>
</dependency>

2.2 FlatBuffers Schema File (.fbs)

In FlatBuffers, data structures are defined using a schema file with the extension .fbs. This file specifies the layout of the data structure including its fields and their types. Let’s look at an example schema file defining a person object:

// Define schema in a .fbs file
table Person {
    name: string;
    age: int;
    hobbies: [string];
}

In this schema, we define a table named “Person” with three fields: “name” of type string, “age” of type int, and “hobbies” as an array of strings. This schema serves as a blueprint for generating code to work with the defined data structure during the serialization and deserialization process.

2.3 Working With FlatBuffers

Once we have defined the schema, we can use the FlatBuffers code generator to generate Java classes that correspond to the schema. These generated classes provide methods for creating, accessing, and manipulating instances of the defined data structure. The Person class will be generated by the FlatBuffer compiler (flatc) based on the schema provided and will contain the classes and methods required to manipulate the defined data structure. Thankfully all this is done by the IDE automatically since we’ve included the necessary dependency in the project.

Here’s an example Java code snippet:

// Java code to serialize and deserialize
package com.jcg.example;

import com.google.flatbuffers.FlatBufferBuilder;
import com.example.Person;

public class Main {
    public static void main(String[] args) {
        // Create FlatBufferBuilder
        FlatBufferBuilder builder = new FlatBufferBuilder();

        // Create hobbies strings
        int[] hobbies = {
            builder.createString("Reading"),
            builder.createString("Gaming")
        };

        // Serialize person object
        int personOffset = Person.createPerson(builder, builder.createString("John"), 30, Person.createHobbiesVector(builder, hobbies));
        builder.finish(personOffset);

        // Deserialize person object
        byte[] buf = builder.sizedByteArray();
        ByteBuffer bb = ByteBuffer.wrap(buf);
        Person person = Person.getRootAsPerson(bb);

        // Access deserialized data
        System.out.println("Name: " + person.name());
        System.out.println("Age: " + person.age());
        for (int i = 0; i < person.hobbiesLength(); i++) {
            System.out.println("Hobby " + (i+1) + ": " + person.hobbies(i));
        }
    }
}

In this code, we use the FlatBufferBuilder to create a FlatBuffer instance representing a person object with the name “John”, age 30, and hobbies “Reading” and “Gaming”. We then serialize this object, deserialize it back, and access the deserialized data for printing.

2.3.1 Code Output

The code output shows the deserialized data after serializing and then deserializing the person object using FlatBuffers in Java.

Name: John
Age: 30
Hobby 1: Reading
Hobby 2: Gaming

2.4 JSON Conversion Using FlatBuffers

Converting FlatBuffers data to JSON format is straightforward. FlatBuffers provides methods to serialize FlatBuffers objects into JSON strings directly. These methods automatically generate JSON representations of the data based on the schema definition, making it easy to work with JSON data in FlatBuffers applications.

Consider a simple example where we have a schema for a person with fields like name, age, and hobbies. We can define this schema in a .fbs file and generate Java classes using FlatBuffers code generation tools. Then, we can parse JSON data into FlatBuffers objects and vice versa using the generated code.

import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.FlexBuffers;

public class Main {
    public static void main(String[] args) {
        // Define schema for a person
        String schema = "table Person { name:string; age:int; hobbies:[string]; }";
        
        // Create FlatBufferBuilder
        FlatBufferBuilder builder = new FlatBufferBuilder();
        
        // Start building FlatBuffer
        int nameOffset = builder.createString("John");
        int[] hobbiesOffsets = { builder.createString("Reading"), builder.createString("Gaming") };
        int hobbiesVector = Person.createHobbiesVector(builder, hobbiesOffsets);
        Person.startPerson(builder);
        Person.addName(builder, nameOffset);
        Person.addAge(builder, 30);
        Person.addHobbies(builder, hobbiesVector);
        int personOffset = Person.endPerson(builder);
        Person.finishPersonBuffer(builder, personOffset);

        // Serialize FlatBuffer to JSON
        byte[] flatBufferBytes = builder.sizedByteArray();
        FlexBuffers.TypedBuffer buffer = FlexBuffers.getRoot(new FlexBuffers.ByteBufferWrapper(flatBufferBytes));
        String json = buffer.toJson(schema);

        // Print JSON representation
        System.out.println("JSON representation:");
        System.out.println(json);

        // Deserialize JSON to FlatBuffer
        FlexBuffers.Builder flexBuilder = new FlexBuffers.Builder();
        flexBuilder.fromJson(json, schema);
        FlexBuffers.TypedBuffer typedBuffer = flexBuilder.finish();
        byte[] flatBufferFromJson = typedBuffer.toByteArray();

        // Access FlatBuffer data
        ByteBuffer byteBuffer = ByteBuffer.wrap(flatBufferFromJson);
        Person person = Person.getRootAsPerson(byteBuffer);
        System.out.println("\nDeserialized data:");
        System.out.println("Name: " + person.name());
        System.out.println("Age: " + person.age());
        System.out.println("Hobbies:");
        for (int i = 0; i < person.hobbiesLength(); i++) {
            System.out.println("- " + person.hobbies(i));
        }
    }
}

In this example, we define a schema for a person with fields like name, age, and hobbies. We then create a FlatBuffer representing a person object with some sample data. We serialize this FlatBuffer to JSON format using FlexBuffers. After that, we deserialize the JSON back to a FlatBuffer and access the data.

2.4.1 Code Output

The output of the above code will be:

JSON representation:
{
  "name": "John",
  "age": 30,
  "hobbies": ["Reading", "Gaming"]
}

Deserialized data:
Name: John
Age: 30
Hobbies:
- Reading
- Gaming

3. Conclusion

Working with FlatBuffers is like having a superpower for storing and organizing data in computer programs. You start by describing how your data should look in a special file called a schema. Then, you use a tool to generate code based on that schema. This code helps you manage your data easily and quickly, without sacrificing speed.

FlatBuffers is great because it lets you directly access your data in its compact, serialized form, making it fast and efficient. Plus, it’s flexible – even if you change your data structure later on, FlatBuffers can handle it smoothly.

One cool thing about FlatBuffers is that it can easily convert data between its own format and JSON, which is a common way of representing data. This means you can use FlatBuffers to work with JSON data without slowing down your program.

Overall, FlatBuffers makes it simple to handle data in your programs. Whether you’re storing information or sharing it between different systems, FlatBuffers has got you covered with its easy-to-use tools and speedy performance.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button