How to Implement Custom Serialization for a Collection in Java?

How to Implement Custom Serialization for a Collection in Java?

Introduction to Serialization in Java

Serialization in Java refers to the process of converting an object into a byte stream so that it can be saved to a file or sent over the network. Java provides a default serialization mechanism through the Serializable interface. However, there are cases when you need more control over how an object is serialized, especially when working with collections such as lists, sets, or maps.

In this article, we will explore how to implement custom serialization for collections in Java. We will look at scenarios where the default serialization may not be suitable, and provide a solution through custom serialization techniques.

Understanding the Need for Custom Serialization

By default, when a class implements the Serializable interface, all the fields of the class are serialized, including fields of its collection members. But this may not always be desirable. For example:

  • Some fields may be transient and should not be serialized.
  • You may need to store collections in a different format (e.g., compressing or encrypting them).
  • The collection may contain objects that need custom serialization logic.

In such cases, Java allows you to implement custom serialization by overriding the writeObject and readObject methods, which control how objects are serialized and deserialized.

Steps to Implement Custom Serialization for a Collection in Java

Let’s walk through an example where we customize the serialization process of a List of objects. Suppose we have a class Student that holds details about students, and we want to serialize a collection of these students.

Step 1: Define the Student Class


import java.io.*;

public class Student implements Serializable {
    private String name;
    private int age;
    private transient String password;  // 'transient' means this field will not be serialized

    public Student(String name, int age, String password) {
        this.name = name;
        this.age = age;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getPassword() {
        return password;
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + ", password='" + password + "'}";
    }
}
        

In this class, we have a password field marked as transient, meaning it will not be serialized by default. Now, we will serialize a collection of Student objects in a custom way.

Step 2: Create the Custom Serialization Logic

To customize serialization, we need to implement two methods in the class holding the collection: writeObject and readObject.

writeObject Method


import java.io.*;
import java.util.List;

public class StudentList implements Serializable {
    private List students;

    public StudentList(List students) {
        this.students = students;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        // Custom serialization logic
        out.defaultWriteObject();  // Serialize the default fields first

        // Serialize the collection with custom format
        out.writeInt(students.size());
        for (Student student : students) {
            out.writeObject(student.getName());
            out.writeInt(student.getAge());
            out.writeObject(student.getPassword());  // Custom handling of password
        }
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        // Custom deserialization logic
        in.defaultReadObject();  // Deserialize default fields first

        // Deserialize the collection with custom format
        int size = in.readInt();
        students = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            String name = (String) in.readObject();
            int age = in.readInt();
            String password = (String) in.readObject();  // Handle password deserialization
            students.add(new Student(name, age, password));
        }
    }

    @Override
    public String toString() {
        return "StudentList{" +
                "students=" + students +
                '}';
    }
}
        

In this example, the writeObject method serializes each Student object in a custom manner by explicitly writing individual fields, while the readObject method handles the deserialization of each field. The password field, even though marked as transient, is manually serialized and deserialized in this case, providing flexibility.

Step 3: Test Custom Serialization

Now, let’s test our custom serialization implementation by writing and reading a StudentList object to and from a file.


import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        try {
            // Create some sample students
            List students = new ArrayList<>();
            students.add(new Student("Alice", 20, "alicepassword"));
            students.add(new Student("Bob", 22, "bobpassword"));

            // Create a StudentList object
            StudentList studentList = new StudentList(students);

            // Serialize the object
            try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("students.dat"))) {
                out.writeObject(studentList);
            }

            // Deserialize the object
            try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("students.dat"))) {
                StudentList deserializedStudentList = (StudentList) in.readObject();
                System.out.println("Deserialized StudentList: " + deserializedStudentList);
            }

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
        

When you run this program, the StudentList object will be serialized to the students.dat file, and the data will be deserialized back into a StudentList object with the custom serialization logic applied.

Conclusion

Custom serialization provides a way to tailor the serialization process to meet your application's specific needs. By overriding the writeObject and readObject methods, you gain control over how objects, especially collections, are serialized and deserialized. This is particularly useful when dealing with complex objects or collections with custom fields and behaviors.

In this guide, we demonstrated how to implement custom serialization for a collection in Java. We explored how to handle serialization of fields, including transient fields, and how to manage collections like List objects. By using this approach, you can ensure that your application’s serialization behavior aligns with its requirements.

© 2025 Tech Interview Guide. All rights reserved.

Please follow and like us:

Leave a Comment