Jackson এবং Immutable Objects

জ্যাকসন (Jackson) - Java Technologies

330

Jackson-এ Immutable Objects (যে অবজেক্টগুলির ফিল্ড পরিবর্তনযোগ্য নয়) সিরিয়ালাইজ এবং ডি-সিরিয়ালাইজ করার জন্য কিছু কনফিগারেশন এবং অ্যাপ্রোচ দরকার। Immutable Objects সাধারণত ফাইনাল ফিল্ড এবং কোনও পাবলিক সেটার মেথড ছাড়া থাকে। Jackson এই ধরনের অবজেক্ট হ্যান্ডল করার জন্য পূর্ণ সমর্থন প্রদান করে।


Immutable Objects এবং Jackson

Immutable Objects-এর ক্ষেত্রে সাধারণ সমস্যাটি হলো যে Jackson ডিফল্টভাবে ডি-সিরিয়ালাইজেশনের সময় ডিফল্ট কন্সট্রাক্টর এবং সেটার মেথড ব্যবহার করে। Immutable Objects-এ যেহেতু এগুলো থাকে না, তাই আমাদের এই সমস্যা সমাধানের জন্য কিছু বিকল্প পদ্ধতি ব্যবহার করতে হয়।


পদ্ধতিগুলো

1. @JsonCreator এবং @JsonProperty ব্যবহার করে কন্সট্রাকটরের মাধ্যমে ডি-সিরিয়ালাইজেশন

এই পদ্ধতিতে আপনি কন্সট্রাকটর ব্যবহার করে ডি-সিরিয়ালাইজ করবেন। Jackson কন্সট্রাকটরের প্যারামিটারগুলো ম্যাপ করার জন্য @JsonProperty ব্যবহার করে।

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ImmutableExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Serialize
        Person person = new Person("John Doe", 30);
        String json = mapper.writeValueAsString(person);
        System.out.println("Serialized JSON: " + json);

        // Deserialize
        Person deserializedPerson = mapper.readValue(json, Person.class);
        System.out.println("Deserialized Person: " + deserializedPerson);
    }
}

class Person {
    private final String name;
    private final int age;

    @JsonCreator
    public Person(@JsonProperty("name") String name, @JsonProperty("age") int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

Output:

Serialized JSON: {"name":"John Doe","age":30}
Deserialized Person: Person{name='John Doe', age=30}

2. ObjectMapper এর Module Configuration ব্যবহার করে

jackson-datatype-jdk8 মডিউল ব্যবহার করে Immutable Objects-এর জন্য ডিফল্ট টাইপ হ্যান্ডল করা যায়।

Maven Dependency:
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
    <version>2.15.2</version>
</dependency>
Usage:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

public class ImmutableExampleWithModule {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jdk8Module()); // Register the JDK8 module

        // Serialize
        Employee employee = new Employee("Alice", "HR");
        String json = mapper.writeValueAsString(employee);
        System.out.println("Serialized JSON: " + json);

        // Deserialize
        Employee deserializedEmployee = mapper.readValue(json, Employee.class);
        System.out.println("Deserialized Employee: " + deserializedEmployee);
    }
}

class Employee {
    private final String name;
    private final String department;

    public Employee(String name, String department) {
        this.name = name;
        this.department = department;
    }

    public String getName() {
        return name;
    }

    public String getDepartment() {
        return department;
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', department='" + department + "'}";
    }
}

3. Custom Deserializer ব্যবহার করা

আপনি কাস্টম ডি-সিরিয়ালাইজার ব্যবহার করতে পারেন যদি আপনার আরও জটিল Immutable Object থাকে।

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;

public class CustomDeserializerExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Register custom deserializer
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Project.class, new ProjectDeserializer());
        mapper.registerModule(module);

        // Deserialize
        String json = "{\"name\":\"Project X\",\"budget\":50000}";
        Project project = mapper.readValue(json, Project.class);
        System.out.println("Deserialized Project: " + project);
    }
}

class Project {
    private final String name;
    private final int budget;

    public Project(String name, int budget) {
        this.name = name;
        this.budget = budget;
    }

    public String getName() {
        return name;
    }

    public int getBudget() {
        return budget;
    }

    @Override
    public String toString() {
        return "Project{name='" + name + "', budget=" + budget + '}';
    }
}

// Custom Deserializer
class ProjectDeserializer extends JsonDeserializer<Project> {
    @Override
    public Project deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
        String name = parser.readValueAsTree().get("name").asText();
        int budget = parser.readValueAsTree().get("budget").asInt();
        return new Project(name, budget);
    }
}

  • Immutable Objects এর জন্য Jackson-এর @JsonCreator এবং @JsonProperty সবচেয়ে সহজ এবং কার্যকর পদ্ধতি।
  • মডিউল যোগ করে সহজে Immutable Object হ্যান্ডল করা যায়।
  • জটিল কেসে কাস্টম ডি-সিরিয়ালাইজার ব্যবহার করতে পারেন।

Jackson এবং Immutable Objects একত্রে ব্যবহার করার জন্য এই পদ্ধতিগুলো ব্যবহার করে আপনার কোড আরও রিডেবল এবং কার্যকরী হতে পারে।

Content added By

Java-তে Immutable Objects এমন ক্লাসগুলোর ইনস্ট্যান্স, যা একবার তৈরি হলে পরিবর্তন করা যায় না। Immutable ক্লাস তৈরির সাধারণ বৈশিষ্ট্যগুলোর মধ্যে থাকে:

  • ক্লাসটি final হওয়া।
  • ফিল্ডগুলো final হওয়া।
  • কোনো setter মেথড না থাকা।
  • কনস্ট্রাক্টর দিয়ে ফিল্ডগুলো নির্ধারণ করা।

Jackson লাইব্রেরি Immutable Objects-এর সাথে কাজ করতে পারে এবং যথাযথ পদ্ধতিতে Serialization ও Deserialization নিশ্চিত করে।


Serialization of Immutable Objects

Immutable Objects এর Serialization করা সহজ। Jackson স্বয়ংক্রিয়ভাবে Getter মেথডগুলো ব্যবহার করে JSON তৈরির জন্য।

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;

public class ImmutableSerializationExample {
    public static void main(String[] args) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();

            // Immutable Object তৈরি
            ImmutableUser user = new ImmutableUser(1, "Rahim", "rahim@example.com");

            // Object থেকে JSON
            String json = objectMapper.writeValueAsString(user);

            System.out.println("Serialized JSON: " + json);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// Immutable Class
final class ImmutableUser {
    private final int id;
    private final String name;
    private final String email;

    public ImmutableUser(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

আউটপুট:

Serialized JSON: {"id":1,"name":"Rahim","email":"rahim@example.com"}

Deserialization of Immutable Objects

Deserialization করার সময় Jackson ডিফল্টভাবে ডিফল্ট কনস্ট্রাক্টর (no-args constructor) ব্যবহার করে এবং setter মেথড কল করে। কিন্তু Immutable Objects-এ এগুলো থাকে না।

এই সমস্যার সমাধানের জন্য আমরা @JsonCreator এবং @JsonProperty এনোটেশন ব্যবহার করতে পারি।


উদাহরণ:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ImmutableDeserializationExample {
    public static void main(String[] args) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();

            // JSON String
            String json = "{\"id\":1,\"name\":\"Rahim\",\"email\":\"rahim@example.com\"}";

            // JSON থেকে Object
            ImmutableUser user = objectMapper.readValue(json, ImmutableUser.class);

            System.out.println("Deserialized User: " + user.getName() + " - " + user.getEmail());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// Immutable Class
final class ImmutableUser {
    private final int id;
    private final String name;
    private final String email;

    @JsonCreator
    public ImmutableUser(
        @JsonProperty("id") int id,
        @JsonProperty("name") String name,
        @JsonProperty("email") String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

আউটপুট:

Deserialized User: Rahim - rahim@example.com

গুরুত্বপূর্ণ পয়েন্ট

  1. Serialization:
    • Immutable Objects-এ getter মেথড থাকলেই Jackson JSON তৈরি করতে পারে।
    • ফিল্ডের অ্যাক্সেস সরাসরি প্রয়োজন হয় না।
  2. Deserialization:
    • ডিফল্ট কনস্ট্রাক্টর না থাকলে @JsonCreator ব্যবহার করতে হবে।
    • প্রতিটি ফিল্ডের জন্য @JsonProperty ব্যবহার করতে হবে।

Factory Method ব্যবহার করে Deserialization

আপনি Factory Method দিয়ে Immutable Object তৈরি করতে পারেন। এ ক্ষেত্রে @JsonCreator সরাসরি Factory Method-এর উপর প্রয়োগ করা হয়।

উদাহরণ:

final class ImmutableUser {
    private final int id;
    private final String name;
    private final String email;

    private ImmutableUser(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    @JsonCreator
    public static ImmutableUser createUser(
        @JsonProperty("id") int id,
        @JsonProperty("name") String name,
        @JsonProperty("email") String email) {
        return new ImmutableUser(id, name, email);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

Record ব্যবহার করে Immutable Objects

Java 14+ থেকে, Records ব্যবহার করে সহজে Immutable Objects তৈরি করা যায়। Jackson Records-এর সাথে সহজেই কাজ করতে পারে।

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;

public class RecordExample {
    public static void main(String[] args) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();

            // JSON String
            String json = "{\"id\":1,\"name\":\"Rahim\",\"email\":\"rahim@example.com\"}";

            // JSON থেকে Record Object
            UserRecord user = objectMapper.readValue(json, UserRecord.class);

            System.out.println("Deserialized User Record: " + user.name());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

record UserRecord(int id, String name, String email) {}

আউটপুট:

Deserialized User Record: Rahim

  1. Immutable Objects-এ Serialization স্বাভাবিকভাবে হয়, কারণ getter মেথড ব্যবহার হয়।
  2. Deserialization-এ @JsonCreator এবং @JsonProperty প্রয়োজন।
  3. Java 14+ এ Records ব্যবহার করে Immutable Objects তৈরি করা আরও সহজ।
  4. Factory Method এবং কনস্ট্রাক্টর দুই ক্ষেত্রেই Jackson সহজেই কাজ করতে পারে।
Content added By

Java 14 থেকে শুরু করে records ফিচারটি চালু হয়েছে, যা একটি সংক্ষিপ্ত ডেটা-কেন্দ্রিক ক্লাস তৈরি করার সহজ উপায় প্রদান করে। Jackson লাইব্রেরি স্বাভাবিকভাবেই Java records এর সাথে কাজ করতে পারে, কারণ records এর সকল ফিল্ড final এবং public getter মেথড ব্যবহার করে অ্যাক্সেস করা যায়।


Java Record এর সাথে Jackson Integration

Step 1: Maven Dependency

প্রথমে, Jackson লাইব্রেরি আপনার প্রোজেক্টে যোগ করুন।

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

Step 2: Record Definition

নিচে একটি record উদাহরণ দেওয়া হয়েছে, যা একটি Person ডেটা মডেল হিসেবে কাজ করবে:

public record Person(String name, int age, String city) {}

Step 3: JSON Serialization এবং Deserialization

Jackson-এর ObjectMapper ব্যবহার করে আমরা সহজেই JSON ডেটা সিরিয়ালাইজ (Object to JSON) এবং ডেসিরিয়ালাইজ (JSON to Object) করতে পারি।

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonWithRecords {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        // Creating a record instance
        Person person = new Person("John Doe", 30, "Dhaka");

        // Serialize: Java Record to JSON
        String json = objectMapper.writeValueAsString(person);
        System.out.println("Serialized JSON: " + json);

        // Deserialize: JSON to Java Record
        String jsonInput = """
        {
          "name": "Jane Doe",
          "age": 25,
          "city": "Chittagong"
        }
        """;

        Person deserializedPerson = objectMapper.readValue(jsonInput, Person.class);
        System.out.println("Deserialized Record: " + deserializedPerson);
    }
}

Output

Serialized JSON

{
  "name": "John Doe",
  "age": 30,
  "city": "Dhaka"
}

Deserialized Record

Deserialized Record: Person[name=Jane Doe, age=25, city=Chittagong]

কাস্টমাইজড Jackson Configuration (Optional)

records এর সাথে যদি ডেটা ফরম্যাট বা ডেসিরিয়ালাইজেশনের সময় কোনো বিশেষ কাস্টমাইজেশন প্রয়োজন হয়, তাহলে @JsonProperty বা অন্যান্য Jackson অ্যানোটেশন ব্যবহার করা যেতে পারে।

Field Aliasing using @JsonProperty

import com.fasterxml.jackson.annotation.JsonProperty;

public record Person(
    @JsonProperty("full_name") String name,
    @JsonProperty("years_old") int age,
    @JsonProperty("home_city") String city
) {}

Input JSON

{
  "full_name": "John Doe",
  "years_old": 30,
  "home_city": "Dhaka"
}

Jackson এই JSON কে Person রেকর্ডে ডেসিরিয়ালাইজ করবে এবং নির্দিষ্ট কাস্টম প্রপার্টি নাম অনুযায়ী ফিল্ডগুলো সেট করবে।


Record Integration সুবিধা

  1. Immutable Data Handling: records এর ফিল্ডগুলো স্বয়ংক্রিয়ভাবে final হয়, যা Immutable ডেটা মডেল তৈরি করে।
  2. Boilerplate Code Removal: Constructor, Getters, toString, equals, এবং hashCode স্বয়ংক্রিয়ভাবে জেনারেট হয়।
  3. Natural Compatibility: Jackson স্বাভাবিকভাবেই record টাইপ সাপোর্ট করে, অতিরিক্ত কনফিগারেশনের প্রয়োজন নেই।

ব্যবহার ক্ষেত্র

  • REST API Models: Immutable ডেটা মডেলের জন্য আদর্শ।
  • Microservices Communication: JSON-ভিত্তিক ডেটা আদান-প্রদানে Immutable রেকর্ড ব্যবহার।
  • Configuration Objects: Immutable কনফিগারেশন ডেটা সংরক্ষণের জন্য।

Java Records এবং Jackson-এর ইন্টিগ্রেশন অত্যন্ত কার্যকর, বিশেষ করে Immutable এবং Concise ডেটা মডেল তৈরির জন্য। Record-এর সরলতা এবং Jackson-এর শক্তিশালী JSON প্রসেসিং ক্ষমতা একসঙ্গে মিলে JSON ডেটার সাথে কাজ করার একটি সহজ এবং কার্যকর উপায় প্রদান করে।

Content added By

Jackson ডিফল্টভাবে POJO (Plain Old Java Object) এর গেটার এবং সেটার ব্যবহার করে ডেটা সিরিয়ালাইজ ও ডেসিরিয়ালাইজ করে। তবে Constructor-based Injection এবং Immutable Class এর ক্ষেত্রে এই প্রক্রিয়া সরাসরি কাজ করে না, কারণ Immutable Class-এ সাধারণত সেটার মেথড থাকে না। এজন্য Jackson-কে কনস্ট্রাক্টর ব্যবহার করে এই ধরনের ক্লাস হ্যান্ডল করতে উপযুক্ত কনফিগারেশন প্রয়োজন।


Constructor-based Injection হ্যান্ডল করা

উদাহরণ:

একটি Immutable Class যেখানে শুধুমাত্র কনস্ট্রাক্টর ব্যবহার করে ফিল্ড ভ্যালু সেট করা হয়।

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class User {
    private final String name;
    private final int age;

    // Constructor-based Injection
    @JsonCreator
    public User(@JsonProperty("name") String name, @JsonProperty("age") int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
ব্যাখ্যা:
  1. @JsonCreator:
    • Jackson-কে নির্দেশ করে যে এই কনস্ট্রাক্টরটি ডেসিরিয়ালাইজেশনের সময় ব্যবহার করতে হবে।
  2. @JsonProperty:
    • JSON ডেটার কী (key) এবং কনস্ট্রাক্টরের প্যারামিটারগুলোর মধ্যে ম্যাপিং নির্ধারণ করে।

Serialization এবং Deserialization উদাহরণ

Serialization:

import com.fasterxml.jackson.databind.ObjectMapper;

public class SerializationExample {
    public static void main(String[] args) throws Exception {
        User user = new User("Jackson", 30);

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(user);

        System.out.println("Serialized JSON: " + json);
    }
}
Output:
{
  "name": "Jackson",
  "age": 30
}

Deserialization:

public class DeserializationExample {
    public static void main(String[] args) throws Exception {
        String json = "{ \"name\": \"Jackson\", \"age\": 30 }";

        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(json, User.class);

        System.out.println("Deserialized User: Name = " + user.getName() + ", Age = " + user.getAge());
    }
}
Output:
Deserialized User: Name = Jackson, Age = 30

Immutable Class হ্যান্ডল করা

Immutable Class উদাহরণ:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Employee {
    private final String id;
    private final String name;

    @JsonCreator
    public Employee(@JsonProperty("id") String id, @JsonProperty("name") String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

Serialization এবং Deserialization:

public class ImmutableClassExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Serialization
        Employee employee = new Employee("E123", "John Doe");
        String json = mapper.writeValueAsString(employee);
        System.out.println("Serialized JSON: " + json);

        // Deserialization
        String inputJson = "{ \"id\": \"E123\", \"name\": \"John Doe\" }";
        Employee deserializedEmployee = mapper.readValue(inputJson, Employee.class);
        System.out.println("Deserialized Employee: ID = " + deserializedEmployee.getId() + ", Name = " + deserializedEmployee.getName());
    }
}
Output:
Serialized JSON: {"id":"E123","name":"John Doe"}
Deserialized Employee: ID = E123, Name = John Doe

Jackson-এ Record টাইপ (Java 14+) এর সমর্থন

Java 14 থেকে Records নামে একটি ফিচার যোগ হয়েছে যা Immutable Class তৈরির জন্য একটি সহজ পদ্ধতি। Jackson স্বয়ংক্রিয়ভাবে Records হ্যান্ডল করতে পারে।

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;

public record Product(String id, String name, double price) {}

public class RecordExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Serialization
        Product product = new Product("P001", "Laptop", 799.99);
        String json = mapper.writeValueAsString(product);
        System.out.println("Serialized JSON: " + json);

        // Deserialization
        String inputJson = "{ \"id\": \"P001\", \"name\": \"Laptop\", \"price\": 799.99 }";
        Product deserializedProduct = mapper.readValue(inputJson, Product.class);
        System.out.println("Deserialized Product: ID = " + deserializedProduct.id() + ", Name = " + deserializedProduct.name());
    }
}
Output:
Serialized JSON: {"id":"P001","name":"Laptop","price":799.99}
Deserialized Product: ID = P001, Name = Laptop

Constructor-based Injection vs Default Behavior

বৈশিষ্ট্যSetter-based InjectionConstructor-based Injection
মেমোরি ব্যবস্থাপনাফিল্ড আলাদাভাবে সেট হয়।ইনস্ট্যান্স তৈরির সময় সব ফিল্ড সেট হয়।
Immutable Supportসরাসরি সমর্থন নেই।Immutable ক্লাস সরাসরি সমর্থিত।
Jackson কনফিগারেশনডিফল্ট মডেল।@JsonCreator এবং @JsonProperty প্রয়োজন।

সাধারণ সমস্যা এবং সমাধান

১. "No Creators, like default constructor" Error

  • Immutable Class-এ ডিফল্ট কনস্ট্রাক্টর না থাকলে Jackson ডেসিরিয়ালাইজ করতে পারে না।
  • সমাধান: @JsonCreator এবং @JsonProperty ব্যবহার করুন।

২. Missing Default Constructor

  • Jackson ডিফল্টভাবে ডিফল্ট কনস্ট্রাক্টর খোঁজে।
  • সমাধান: Immutable Class-এর ক্ষেত্রে @JsonCreator ব্যবহার বাধ্যতামূলক।

৩. Custom Field Mapping

  • JSON ফিল্ডের নাম এবং কনস্ট্রাক্টরের প্যারামিটার নাম ভিন্ন হলে সমস্যা হয়।
  • সমাধান: @JsonProperty দিয়ে ফিল্ড ম্যাপিং নিশ্চিত করুন।

  1. Immutable Class এবং Constructor-based Injection হ্যান্ডল করতে Jackson শক্তিশালী সমর্থন প্রদান করে।
  2. @JsonCreator এবং @JsonProperty সঠিকভাবে ব্যবহার করলে Immutable ক্লাসের সাথে সহজে কাজ করা যায়।
  3. Java Records এর জন্য Jackson এর বিল্ট-ইন সমর্থন উন্নত পারফরম্যান্স এবং কোডের সরলতা নিশ্চিত করে।
Content added By

Immutable Data Structures জাভাতে এমন ডেটা স্ট্রাকচার যা একবার তৈরি হলে পরিবর্তন করা যায় না। Immutable ক্লাস Serialize এবং Deserialize করতে হলে কিছু কনফিগারেশন প্রয়োজন হয় কারণ Immutable ক্লাসে সাধারণত setter মেথড থাকে না।

Jackson লাইব্রেরি Immutable ক্লাস হ্যান্ডল করার জন্য সহজ এবং কার্যকর পদ্ধতি প্রদান করে। নিচে বিস্তারিত আলোচনা করা হলো:


1. Immutable Class Serialization

Immutable ক্লাস Serialize করা সহজ কারণ এটি কেবলমাত্র ডেটা পড়ার প্রপার্টি (getter) প্রয়োজন।

উদাহরণ: Immutable Class Serialization

import com.fasterxml.jackson.databind.ObjectMapper;

class Person {
    private final String name;
    private final int age;

    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getters only (No setters)
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class ImmutableSerializationExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Immutable Object তৈরি
        Person person = new Person("John Doe", 30);

        // Serialize
        String json = mapper.writeValueAsString(person);
        System.out.println("Serialized JSON: " + json);
    }
}

আউটপুট:

{
  "name": "John Doe",
  "age": 30
}

2. Immutable Class Deserialization

Deserialize করার সময় সমস্যার কারণ হতে পারে:

  1. Immutable ক্লাসের কোনো setter থাকে না।
  2. ফিল্ডগুলো final হওয়ায় সরাসরি পরিবর্তন সম্ভব নয়।

Jackson এর দুটি পদ্ধতি দিয়ে Immutable ক্লাস Deserialize করা যায়:

  • Constructor-based Deserialization
  • Builder Pattern

2.1 Constructor-based Deserialization

Jackson @JsonCreator এবং @JsonProperty অ্যানোটেশন ব্যবহার করে Constructor-based Deserialization সমর্থন করে।

উদাহরণ: Constructor-based Deserialization

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

class Employee {
    private final String name;
    private final int id;

    // Constructor with @JsonCreator and @JsonProperty
    @JsonCreator
    public Employee(@JsonProperty("name") String name, @JsonProperty("id") int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', id=" + id + '}';
    }
}

public class ConstructorBasedDeserializationExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        String json = "{\"name\":\"Alice\",\"id\":101}";

        // Deserialize
        Employee employee = mapper.readValue(json, Employee.class);
        System.out.println("Deserialized Object: " + employee);
    }
}

আউটপুট:

Deserialized Object: Employee{name='Alice', id=101}

2.2 Builder Pattern

Builder Pattern ব্যবহার করলে Immutable ক্লাসের জন্য আরও ফ্লেক্সিবিলিটি পাওয়া যায়। Jackson @JsonPOJOBuilder এবং @JsonDeserialize অ্যানোটেশন ব্যবহার করে Builder Pattern সমর্থন করে।

উদাহরণ: Builder Pattern

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

@JsonDeserialize(builder = Product.Builder.class)
class Product {
    private final String name;
    private final double price;

    private Product(Builder builder) {
        this.name = builder.name;
        this.price = builder.price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Product{name='" + name + "', price=" + price + '}';
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class Builder {
        private String name;
        private double price;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder price(double price) {
            this.price = price;
            return this;
        }

        public Product build() {
            return new Product(this);
        }
    }
}

public class BuilderPatternExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        String json = "{\"name\":\"Laptop\",\"price\":75000.0}";

        // Deserialize
        Product product = mapper.readValue(json, Product.class);
        System.out.println("Deserialized Object: " + product);
    }
}

আউটপুট:

Deserialized Object: Product{name='Laptop', price=75000.0}

3. টিপস এবং সুপারিশ

(a) Preferred Approach

  • যদি Immutable ক্লাস ছোট এবং সরল হয়, Constructor-based Deserialization আদর্শ।
  • বড় বা জটিল Immutable ক্লাসের ক্ষেত্রে Builder Pattern বেশি কার্যকর।

(b) Final Fields

  • Immutable ক্লাসের ফিল্ডগুলো final রাখা ভালো, এবং Jackson এগুলো সঠিকভাবে সমর্থন করে।

(c) JSON Validation

  • @JsonProperty ব্যবহার করে প্রপার্টি বাধ্যতামূলক (required) করা যায়:
@JsonProperty(value = "name", required = true)
private final String name;

(d) Global Configuration

Jackson এর ObjectMapper-এ Immutable টাইপ সঠিকভাবে হ্যান্ডল করার জন্য কনফিগারেশন যোগ করা যায়:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

4. Use Cases

  • Immutable Domain Models: যেমন, DTOs বা Value Objects।
  • Configuration Loading: Immutable কনফিগারেশন ক্লাস JSON থেকে লোড করা।
  • REST API Responses: Immutable ক্লাসের মাধ্যমে API রেসপন্স মডেল তৈরি।

Jackson Immutable ক্লাস Serialize এবং Deserialize করার জন্য শক্তিশালী সমাধান প্রদান করে। ছোট ক্লাসের জন্য Constructor-based পদ্ধতি এবং জটিল ক্লাসের জন্য Builder Pattern ব্যবহার করা বেস্ট প্র্যাকটিস।

Content added By
Promotion

Are you sure to start over?

Loading...