Jackson এর Performance Optimization Techniques

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

489

Jackson একটি অত্যন্ত কার্যকর JSON লাইব্রেরি হলেও বড় ডেটা বা উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশন নিয়ে কাজ করার সময় কিছু পারফরম্যান্স অপ্টিমাইজেশন করা প্রয়োজন। নিচে Jackson-এর পারফরম্যান্স উন্নত করার জন্য বিভিন্ন টেকনিক আলোচনা করা হলো:


1. Streaming API ব্যবহার করা

Jackson-এর Streaming API (যেমন JsonParser এবং JsonGenerator) মেমোরি-সাশ্রয়ী এবং দ্রুততর কারণ এটি ডেটাকে টোকেন-ভিত্তিতে প্রসেস করে। বড় JSON ফাইল প্রসেস করার সময় এটি অত্যন্ত কার্যকর।

উদাহরণ: Streaming API

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

import java.io.File;
import java.io.IOException;

public class StreamingExample {
    public static void main(String[] args) throws IOException {
        JsonFactory factory = new JsonFactory();
        File file = new File("output.json");

        try (JsonGenerator generator = factory.createGenerator(file, com.fasterxml.jackson.core.JsonEncoding.UTF8)) {
            generator.writeStartObject();
            generator.writeStringField("name", "John Doe");
            generator.writeNumberField("age", 30);
            generator.writeEndObject();
        }
    }
}

2. ObjectMapper পুনঃব্যবহার করা

ObjectMapper একটি ভারী ও বহুমুখী ক্লাস। এটি প্রতিবার নতুন করে তৈরি না করে singleton pattern বা spring bean হিসেবে ব্যবহার করুন। পুনঃব্যবহার মেমোরি এবং পারফরম্যান্স উভয়ের জন্য ভালো।

উদাহরণ: ObjectMapper Singleton

import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperSingleton {
    private static final ObjectMapper mapper = new ObjectMapper();

    private ObjectMapperSingleton() {}

    public static ObjectMapper getInstance() {
        return mapper;
    }
}

3. Features Disable/Enable করা

Jackson-এর কিছু ফিচার ডিফল্টভাবে চালু থাকে যা প্রয়োজন না হলে বন্ধ করলে পারফরম্যান্স বাড়ে।

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;

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

        // Disable features to optimize performance
        mapper.disable(com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS);
        mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        // Enable features for specific needs
        mapper.enable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    }
}

4. Serialization Views ব্যবহার করা

Serialization Views ব্যবহার করে নির্দিষ্ট প্রোপার্টি সিরিয়ালাইজ করুন। এটি বড় অবজেক্টের ক্ষেত্রে অপ্রয়োজনীয় ডেটা এড়িয়ে পারফরম্যান্স বাড়ায়।

উদাহরণ:

import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.ObjectMapper;

class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

class User {
    @JsonView(Views.Public.class)
    private String name;

    @JsonView(Views.Internal.class)
    private String email;

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

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

        User user = new User("John Doe", "john.doe@example.com");

        // Serialize with Public view
        String json = mapper.writerWithView(Views.Public.class).writeValueAsString(user);
        System.out.println("Public View: " + json);
    }
}

5. Custom Serializer/Deserializer ব্যবহার করা

ডিফল্ট সিরিয়ালাইজার বা ডি-সিরিয়ালাইজারের পরিবর্তে কাস্টম লজিক তৈরি করলে প্রক্রিয়াটি দ্রুততর হতে পারে।

উদাহরণ: Custom Serializer

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

class UserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("name", user.getName());
        gen.writeEndObject();
    }
}

6. Module Usage (e.g., Afterburner Module)

Afterburner Module Jackson-এর পারফরম্যান্স বাড়াতে bytecode generation ব্যবহার করে। এটি বিশেষত সিরিয়ালাইজ এবং ডি-সিরিয়ালাইজেশনের সময় কাজ করে।

Dependency:

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-afterburner</artifactId>
    <version>2.15.2</version>
</dependency>

Usage:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;

public class AfterburnerExample {
    public static void main(String[] args) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new AfterburnerModule());

        // Use this ObjectMapper for high-performance serialization/deserialization
    }
}

7. JSON Views Avoidance (Flat JSON)

জটিল নেস্টেড JSON ফরম্যাটের পরিবর্তে Flat JSON ব্যবহার করুন। এটি প্রসেসিং দ্রুত করে।

Example: Flat JSON Structure

{
  "user_id": 1,
  "user_name": "John Doe",
  "user_age": 30
}

8. Avoid Unnecessary Annotations

প্রয়োজন ছাড়া অতিরিক্ত অ্যানোটেশন ব্যবহার থেকে বিরত থাকুন। এটি প্রসেসিং সময় এবং মেমোরি উভয় সাশ্রয় করে।


9. Precompiled Schema ব্যবহার করা (Avro/Protobuf)

বড় ডেটাসেটের ক্ষেত্রে Avro বা Protobuf-এর মতো প্রি-কম্পাইলড স্কিমা ব্যবহার করা Jackson-এর তুলনায় আরও দ্রুততর হতে পারে।


10. GZIP Compression ব্যবহার করা

JSON ডেটা কম্প্রেশন ব্যবহার করলে ডেটা ট্রান্সমিশন দ্রুত হয়। GZIP দিয়ে JSON ডেটা কম্প্রেস এবং ডিকম্প্রেস করতে পারেন।

Example:

import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPOutputStream;

public class GzipExample {
    public static byte[] compress(String data) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
            gzipOutputStream.write(data.getBytes());
        }
        return byteArrayOutputStream.toByteArray();
    }
}

  • Streaming API: বড় JSON ডেটার জন্য আদর্শ।
  • Afterburner Module: পারফরম্যান্স উন্নত করতে বিশেষত কার্যকর।
  • ObjectMapper Reuse: মেমোরি এবং প্রসেসিং সময় সাশ্রয়।
  • Custom Serializer/Deserializer: নির্দিষ্ট প্রয়োজন অনুযায়ী অপ্টিমাইজ করুন।
  • Flat JSON Structure: সহজ এবং দ্রুত প্রক্রিয়াকরণ।

এই টেকনিকগুলো ব্যবহার করে Jackson-এর মাধ্যমে JSON প্রসেসিং আরও দ্রুত এবং কার্যকর করা সম্ভব।

Content added By

Jackson একটি দ্রুত এবং কার্যকর JSON প্রসেসিং লাইব্রেরি। তবে, Large JSON Files প্রসেস করার সময় মেমোরি ব্যবহারে দক্ষতা এবং কার্যকারিতা নিশ্চিত করা জরুরি।

সমস্যার ধরন

  1. High Memory Usage:
    • পুরো JSON ডেটা মেমোরিতে লোড করা হলে, OutOfMemoryError হতে পারে।
  2. Slow Performance:
    • Traditional Data Binding API বড় JSON ফাইল প্রসেস করতে ধীর গতির হতে পারে।
  3. Unnecessary Overhead:
    • পুরো JSON ডেটা প্রসেস করা সবসময় দরকার হয় না।

Performance Optimization Techniques

১. Streaming API ব্যবহার

Jackson এর Streaming API (যেমন JsonParser এবং JsonGenerator) বড় JSON ফাইল প্রসেস করার জন্য আদর্শ। এটি ডেটা pull-based মডেলে একসাথে একটি করে টোকেন পড়ে এবং মেমোরি ব্যবহার কমায়।

উদাহরণ: JsonParser ব্যবহার করে JSON পড়া
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;

public class StreamingExample {
    public static void main(String[] args) {
        try {
            JsonFactory factory = new JsonFactory();
            JsonParser parser = factory.createParser(new File("large-file.json"));

            while (!parser.isClosed()) {
                JsonToken token = parser.nextToken();
                if (JsonToken.FIELD_NAME.equals(token) && "name".equals(parser.getCurrentName())) {
                    parser.nextToken();
                    System.out.println("Name: " + parser.getValueAsString());
                }
            }

            parser.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
কেন Streaming API?
  • Low Memory Footprint: পুরো JSON ফাইল মেমোরিতে লোড না করেই প্রসেস করা যায়।
  • High Performance: শুধুমাত্র প্রয়োজনীয় অংশ প্রসেস করা যায়।

২. Tree Model API ব্যবহার করে নির্দিষ্ট অংশ প্রসেস করা

Jackson এর Tree Model API ব্যবহার করে পুরো JSON লোড না করেও নির্দিষ্ট অংশে নেভিগেট করা সম্ভব।

উদাহরণ: Tree Model API
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;

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

            // JSON ফাইল থেকে Tree Structure লোড করা
            JsonNode rootNode = mapper.readTree(new File("large-file.json"));

            // নির্দিষ্ট নোড পড়া
            JsonNode nameNode = rootNode.path("name");
            System.out.println("Name: " + nameNode.asText());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
কেন Tree Model API?
  • Selective Parsing: নির্দিষ্ট অংশ প্রসেস করতে কার্যকর।
  • Simple Navigation: JSON এর কাঠামোতে সহজে নেভিগেট করা যায়।

৩. ObjectReader ব্যবহার

ObjectReader ব্যবহার করে মেমোরি ব্যবহারে আরও দক্ষতা বাড়ানো যায়। এটি ObjectMapper এর একটি Lightweight সংস্করণ।

উদাহরণ: ObjectReader
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;

import java.io.File;

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

            // ObjectReader তৈরি
            ObjectReader reader = mapper.readerFor(MyClass.class);

            // JSON থেকে Object
            MyClass myObject = reader.readValue(new File("large-file.json"));
            System.out.println(myObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
কেন ObjectReader?
  • Reusability: একবার কনফিগার করা হলে বারবার ব্যবহার করা যায়।
  • Efficient: ObjectMapper পুনরায় তৈরি করার প্রয়োজন হয় না।

৪. JSON Data Chunking

বড় JSON ফাইল প্রক্রিয়া করার সময় JSON ডেটা অংশে ভাগ করে প্রসেস করা যেতে পারে।

উদাহরণ: JSON Array Chunking
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;

public class ChunkingExample {
    public static void main(String[] args) {
        try {
            JsonFactory factory = new JsonFactory();
            JsonParser parser = factory.createParser(new File("large-file.json"));

            while (!parser.isClosed()) {
                JsonToken token = parser.nextToken();

                if (JsonToken.START_ARRAY.equals(token)) {
                    while (parser.nextToken() != JsonToken.END_ARRAY) {
                        System.out.println(parser.readValueAsTree());
                    }
                }
            }

            parser.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
কেন Chunking?
  • Memory Efficient: একবারে ছোট ছোট অংশ প্রসেস করা যায়।
  • Scalable: বড় JSON ফাইলের জন্য কার্যকর।

৫. Custom Deserialization

আপনার JSON ফাইলের ফরম্যাট অনুযায়ী Custom Deserializer তৈরি করা যায়।

উদাহরণ: Custom Deserializer
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 java.io.File;
import java.io.IOException;

public class CustomDeserializerExample {
    public static void main(String[] args) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.registerModule(new SimpleModule().addDeserializer(MyClass.class, new MyClassDeserializer()));

            MyClass myObject = mapper.readValue(new File("large-file.json"), MyClass.class);
            System.out.println(myObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyClassDeserializer extends JsonDeserializer<MyClass> {
    @Override
    public MyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // Custom logic here
        return new MyClass();
    }
}

৬. Gzip Compression ব্যবহার

বড় JSON ফাইল কমপ্রেস করতে Gzip ব্যবহার করলে পারফরম্যান্স উন্নত হয়।

উদাহরণ: Gzip ব্যবহার
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.FileInputStream;
import java.util.zip.GZIPInputStream;

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

            GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream("large-file.json.gz"));
            MyClass myObject = mapper.readValue(gzipInputStream, MyClass.class);

            System.out.println(myObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Optimization Summary

টেকনিকসুবিধাপ্রযোজ্যতা
Streaming APILow Memory Usageবড় JSON ফাইল প্রসেস করতে
Tree Model APISelective Parsingনির্দিষ্ট অংশ প্রসেস করতে
ObjectReaderEfficiency and Reusabilityএকাধিক JSON প্রসেস করতে
ChunkingMemory EfficientJSON Arrays প্রসেস করতে
Custom DeserializationSpecific Parsing LogicComplex JSON প্রসেস করতে
Gzip CompressionFaster Data Transferকমপ্রেসড ফাইলের জন্য

  1. Jackson এর Streaming API বড় JSON ফাইল প্রসেস করার জন্য সবচেয়ে কার্যকর, কারণ এটি সরাসরি টোকেন নিয়ে কাজ করে।
  2. Chunking এবং Gzip Compression মেমোরি ব্যবহার এবং ডেটা ট্রান্সফার সময় উন্নত করে।
  3. আপনার প্রয়োজন অনুযায়ী সঠিক টেকনিক নির্বাচন করে JSON প্রসেসিং অপ্টিমাইজ করুন।
Content added By

Jackson একটি JSON প্রক্রিয়াকরণ লাইব্রেরি যা JSON serialization এবং deserialization পরিচালনার জন্য খুবই কার্যকর। তবে, বৃহৎ ডেটাসেট বা জটিল JSON ডেটার সাথে কাজ করার সময় memory এবং resource management গুরুত্বপূর্ণ হয়ে ওঠে। নিম্নলিখিত পদ্ধতিগুলি ব্যবহার করে আপনি Jackson এর memory এবং resource management উন্নত করতে পারেন।


Memory এবং Resource Management কৌশল

1. Streaming API (JsonParser এবং JsonGenerator ব্যবহার করা)

Jackson এর Streaming API ব্যবহার করলে বড় JSON ডেটা মেমোরিতে পুরোপুরি লোড না করে স্ট্রিমিং পদ্ধতিতে প্রক্রিয়া করা যায়। এটি memory footprint হ্রাস করতে সাহায্য করে।

JsonParser উদাহরণ (Reading JSON)
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;

public class StreamingExample {
    public static void main(String[] args) throws Exception {
        JsonFactory factory = new JsonFactory();
        try (JsonParser parser = factory.createParser(new File("large-data.json"))) {
            while (!parser.isClosed()) {
                JsonToken token = parser.nextToken();
                if (token == JsonToken.FIELD_NAME) {
                    String fieldName = parser.getCurrentName();
                    System.out.println("Field: " + fieldName);
                }
            }
        }
    }
}
JsonGenerator উদাহরণ (Writing JSON)
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

import java.io.FileWriter;

public class JsonGeneratorExample {
    public static void main(String[] args) throws Exception {
        JsonFactory factory = new JsonFactory();
        try (JsonGenerator generator = factory.createGenerator(new FileWriter("output.json"))) {
            generator.writeStartObject();
            generator.writeStringField("name", "John Doe");
            generator.writeNumberField("age", 30);
            generator.writeEndObject();
        }
    }
}

2. Avoid ObjectMapper Re-Creation

ObjectMapper একটি ভারী-ওজনের অবজেক্ট, এবং এটি বারবার তৈরি করা resource-intensive হতে পারে। এটি একটি singleton বা spring bean হিসাবে ব্যবহার করা উচিত।

Singleton ObjectMapper Example
import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperSingleton {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private ObjectMapperSingleton() {}

    public static ObjectMapper getInstance() {
        return objectMapper;
    }
}

3. Use readTree এবং writeTree সঠিক পরিস্থিতিতে

readTree এবং writeTree API ব্যবহার করলে JSON ডেটাকে tree structure (e.g., JsonNode) হিসাবে প্রক্রিয়া করা যায়। তবে বৃহৎ ডেটার ক্ষেত্রে এটি মেমোরিতে অনেক বেশি জায়গা দখল করতে পারে। তাই শুধুমাত্র যখন প্রয়োজন, তখনই এটি ব্যবহার করুন।

Example
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;

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

        // Read JSON as a tree
        JsonNode rootNode = mapper.readTree(new File("data.json"));
        System.out.println(rootNode.get("name").asText());
    }
}

4. Streaming এবং Tree Model এর সংমিশ্রণ

আপনার প্রয়োজন অনুযায়ী Streaming API এবং Tree Model একত্রিত করতে পারেন। বড় ডেটার জন্য স্ট্রিমিং ব্যবহার করুন এবং ছোট সাবসেটের জন্য JsonNode ব্যবহার করুন।


5. Control Serialization Features

SerializationConfig এবং DeserializationConfig ব্যবহার করে কাস্টম serialization এবং deserialization পরিচালনা করুন, যা memory এবং performance উন্নত করতে পারে।

Example: Disable Default Typing
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

6. Streaming Data Through Input/Output Streams

বড় JSON ডেটার ক্ষেত্রে InputStream এবং OutputStream ব্যবহার করুন। এটি memory-এ ডেটা লোড না করে স্ট্রিমের মাধ্যমে ডেটা প্রক্রিয়া করে।

Example
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

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

        // Read from InputStream
        try (FileInputStream fis = new FileInputStream("large-data.json")) {
            MyObject obj = mapper.readValue(fis, MyObject.class);
            System.out.println(obj);
        }

        // Write to OutputStream
        try (FileOutputStream fos = new FileOutputStream("output.json")) {
            MyObject obj = new MyObject("John", 30);
            mapper.writeValue(fos, obj);
        }
    }
}

7. Manage Large Collections Efficiently

বৃহৎ JSON Arrays বা Collections প্রক্রিয়াকরণের সময় স্ট্রিমিং ব্যবহার করুন।

Example: Using Streaming for Arrays
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;

public class LargeArrayProcessing {
    public static void main(String[] args) throws Exception {
        JsonFactory factory = new JsonFactory();
        try (JsonParser parser = factory.createParser(new File("large-array.json"))) {
            if (parser.nextToken() == JsonToken.START_ARRAY) {
                while (parser.nextToken() != JsonToken.END_ARRAY) {
                    String value = parser.getText();
                    System.out.println(value);
                }
            }
        }
    }
}

8. Avoid Circular References

Hibernate বা bidirectional relationships এর ক্ষেত্রে Circular Reference এড়ানোর জন্য @JsonManagedReference এবং @JsonBackReference ব্যবহার করুন।


Best Practices

  1. Use Streaming for Large Data: বড় JSON ডেটার জন্য স্ট্রিমিং পদ্ধতি ব্যবহার করুন।
  2. Reuse ObjectMapper: ObjectMapper-কে একটি Singleton বা Bean হিসেবে সংরক্ষণ করুন।
  3. Optimize Memory Usage: বৃহৎ ডেটার জন্য InputStream এবং OutputStream ব্যবহার করুন।
  4. Avoid Unnecessary Tree Parsing: শুধুমাত্র প্রয়োজন হলে JsonNode ব্যবহার করুন।
  5. Disable Unused Features: Jackson এর অতিরিক্ত ফিচার বন্ধ করুন যেগুলো আপনার প্রজেক্টে প্রয়োজন নেই।

Jackson JSON প্রক্রিয়াকরণের ক্ষেত্রে শক্তিশালী একটি টুল। তবে, memory এবং resource management নিশ্চিত করতে:

  • Streaming API ব্যবহার করুন বড় JSON ডেটার জন্য।
  • Singleton ObjectMapper ব্যবহার করুন।
  • Input/Output Streams এর মাধ্যমে ডেটা প্রক্রিয়া করুন।
  • Serialization এবং Deserialization এর অতিরিক্ত বৈশিষ্ট্য এড়িয়ে চলুন।

এই পদ্ধতিগুলি memory ও resource management উন্নত করার পাশাপাশি Jackson এর পারফরম্যান্সও বাড়াবে।

Content added By

Jackson ব্যবহার করে Serialization (Java Object থেকে JSON) এবং Deserialization (JSON থেকে Java Object) এর কার্যকারিতা উন্নত করার জন্য কিছু টিপস এবং কৌশল রয়েছে। এই টিপসগুলো মেমোরি ব্যবস্থাপনা, পারফরম্যান্স, এবং ডেটা প্রসেসিংকে আরও কার্যকর করে তোলে।


Serialization এবং Deserialization উন্নত করার টিপস

১. ObjectMapper পুনঃব্যবহার করুন

ObjectMapper একটি ভারী ক্লাস, এবং প্রতিবার নতুন ObjectMapper তৈরি করা পারফরম্যান্স কমিয়ে দেয়।

ভালো পদ্ধতি:
public class ObjectMapperProvider {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static ObjectMapper getInstance() {
        return mapper;
    }
}
  • পুনঃব্যবহারযোগ্য ObjectMapper ব্যবহার করে বারবার নতুন ইনস্ট্যান্স তৈরি এড়ানো যায়।

২. Streaming API ব্যবহার করুন

বড় JSON ডেটা প্রসেস করার সময় মেমোরি ব্যবস্থাপনার জন্য Streaming API ব্যবহার করুন। এটি পুরো JSON লোড না করে অংশে অংশে প্রসেস করতে পারে।

উদাহরণ: JsonParser (Reading JSON)
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class StreamingExample {
    public static void main(String[] args) throws Exception {
        JsonFactory factory = new JsonFactory();
        JsonParser parser = factory.createParser(new File("large_data.json"));

        while (!parser.isClosed()) {
            JsonToken token = parser.nextToken();
            if (JsonToken.FIELD_NAME.equals(token) && "name".equals(parser.getCurrentName())) {
                parser.nextToken();
                System.out.println("Name: " + parser.getValueAsString());
            }
        }
    }
}

৩. Avoid Writing Timestamps

Jackson ডিফল্টভাবে তারিখ এবং সময়কে টাইমস্ট্যাম্প হিসেবে সিরিয়ালাইজ করে। এটি পড়তে বা ডিবাগ করতে কঠিন।

সমাধান:
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
উদাহরণ: LocalDateTime এর জন্য JavaTimeModule:
mapper.registerModule(new JavaTimeModule());

৪. Avoid Unknown Properties

JSON ডেটায় অজানা প্রোপার্টি থাকলে Jackson DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES এর কারণে ব্যর্থ হতে পারে।

সমাধান:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

৫. Custom Serializer এবং Deserializer ব্যবহার করুন

কমপ্লেক্স অবজেক্ট বা কাস্টম ডেটা ফরম্যাটের ক্ষেত্রে কাস্টম Serializer এবং Deserializer ব্যবহার করুন।

Custom Serializer উদাহরণ:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

public class CustomUserSerializer extends StdSerializer<User> {
    public CustomUserSerializer() {
        super(User.class);
    }

    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("user_name", user.getName());
        gen.writeNumberField("user_age", user.getAge());
        gen.writeEndObject();
    }
}

৬. Disable Default Typing

enableDefaultTyping ব্যবহার করলে Jackson টাইপ ইনফরমেশন JSON-এ সংযুক্ত করে, যা নিরাপত্তা এবং পারফরম্যান্স সমস্যার কারণ হতে পারে।

সমাধান:
  • ডিফল্ট টাইপিং এড়ানোর জন্য এটি নিষ্ক্রিয় রাখুন:
mapper.deactivateDefaultTyping();

৭. Use @JsonView for Partial Serialization

সব ফিল্ড JSON-এ অন্তর্ভুক্ত না করার জন্য @JsonView ব্যবহার করুন।

উদাহরণ:
import com.fasterxml.jackson.annotation.JsonView;

class User {
    @JsonView(Views.Public.class)
    public String name;

    @JsonView(Views.Internal.class)
    public int age;
}

class Views {
    public static class Public {}
    public static class Internal extends Public {}
}
ব্যবহার:
String json = mapper.writerWithView(Views.Public.class).writeValueAsString(user);

৮. Avoid Excessive Annotations

Jackson-এ অতিরিক্ত @JsonIgnore, @JsonProperty ইত্যাদি ব্যবহার করলে কোড জটিল হয়ে যায়। প্রয়োজনীয় ক্ষেত্রেই এগুলো ব্যবহার করুন।


৯. Minimize Inclusion with JsonInclude

ডিফল্ট বা null ফিল্ডগুলো JSON থেকে বাদ দেওয়ার জন্য JsonInclude ব্যবহার করুন।

উদাহরণ:
import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
class User {
    public String name;
    public String email;
}

১০. Use Tree Model for Dynamic JSON

যদি JSON ফিল্ডগুলো ডাইনামিক হয় এবং আগে থেকে জানা না থাকে, JsonNode ব্যবহার করুন।

উদাহরণ:
JsonNode node = mapper.readTree(jsonString);
String name = node.get("name").asText();
int age = node.get("age").asInt();

Performance Optimization Summary

টিপসউদ্দেশ্যসুবিধা
ObjectMapper পুনঃব্যবহারObjectMapper বারবার তৈরি করা এড়ানো।পারফরম্যান্স উন্নত এবং কম মেমোরি ব্যবহার।
Streaming APIবড় JSON ডেটা প্রসেস করা।মেমোরি ব্যবস্থাপনা উন্নত।
FAIL_ON_UNKNOWN_PROPERTIES বন্ধ রাখাঅজানা ফিল্ডের কারণে ব্যর্থতা এড়ানো।JSON ডেটার গঠন পরিবর্তিত হলেও ডেসিরিয়ালাইজ সম্ভব।
Custom Serializer/Deserializerজটিল ফিল্ড বা ডেটা ফরম্যাট হ্যান্ডল করা।ফিল্ডগুলোর কাস্টম নিয়ম সংজ্ঞায়িত করা।
@JsonViewআংশিক JSON সিরিয়ালাইজেশন।শুধুমাত্র প্রয়োজনীয় ডেটা অন্তর্ভুক্ত।
Tree Modelডাইনামিক JSON ডেটা প্রসেস।অজানা বা পরিবর্তনশীল ফিল্ড সহজে হ্যান্ডল করা।

Jackson ব্যবহার করে কার্যকর Serialization এবং Deserialization নিশ্চিত করার জন্য:

  1. ObjectMapper পুনঃব্যবহার করুন।
  2. বড় JSON এর ক্ষেত্রে Streaming API ব্যবহার করুন।
  3. নির্দিষ্ট ক্ষেত্রে Custom Serializer/Deserializer ব্যবহার করুন।
  4. Unnecessary Fields বাদ দেওয়ার জন্য JsonInclude এবং @JsonView ব্যবহার করুন।
  5. ডাইনামিক বা বড় JSON প্রসেস করার জন্য Tree Model ব্যবহার করুন।

সঠিক কৌশলগুলো ব্যবহার করলে Jackson-এর মাধ্যমে JSON ডেটা প্রসেসিং দ্রুত, কার্যকর, এবং মেমোরি সাশ্রয়ী হবে।

Content added By

Jackson লাইব্রেরি JSON ডেটা প্রসেস করার জন্য দুইটি শক্তিশালী পদ্ধতি প্রদান করে:

  1. Streaming API: লো-লেভেল JSON প্রসেসিংয়ের জন্য।
  2. Tree Model: JSON ডেটা স্ট্রাকচারকে ডাইনামিকভাবে ম্যানিপুলেট করার জন্য।

1. Streaming API

Streaming API কী?

Streaming API JSON ডেটা প্রসেস করার একটি লাইটওয়েট এবং মেমরি-অপ্টিমাইজড পদ্ধতি। এটি লিনিয়ার ফ্যাশনে JSON ডেটা পড়তে (Parse) এবং লিখতে (Write) ব্যবহার হয়।

কেন ব্যবহার করবেন?

  • Performance: মেমরি খরচ কম।
  • Large JSON: বড় JSON ডেটা স্ট্রিম হিসেবে প্রসেস করতে কার্যকর।

1.1 JSON Parsing (Reading)

Streaming API এর JsonParser ব্যবহার করে JSON ডেটা পড়া হয়।

উদাহরণ: JSON Parsing

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;
import java.io.IOException;

public class StreamingAPIReadExample {
    public static void main(String[] args) throws IOException {
        JsonFactory factory = new JsonFactory();
        JsonParser parser = factory.createParser(new File("data.json"));

        while (!parser.isClosed()) {
            JsonToken token = parser.nextToken();

            if (token == null) break;

            if (JsonToken.FIELD_NAME.equals(token)) {
                String fieldName = parser.getCurrentName();
                parser.nextToken(); // Move to the value
                System.out.println(fieldName + ": " + parser.getText());
            }
        }

        parser.close();
    }
}

JSON ইনপুট (data.json):

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

আউটপুট:

name: John
age: 30
city: Dhaka

1.2 JSON Writing

Streaming API এর JsonGenerator ব্যবহার করে JSON লেখা যায়।

উদাহরণ: JSON Writing

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;

import java.io.File;
import java.io.IOException;

public class StreamingAPIWriteExample {
    public static void main(String[] args) throws IOException {
        JsonFactory factory = new JsonFactory();
        JsonGenerator generator = factory.createGenerator(new File("output.json"));

        generator.writeStartObject(); // Start JSON Object

        generator.writeStringField("name", "John");
        generator.writeNumberField("age", 30);
        generator.writeStringField("city", "Dhaka");

        generator.writeEndObject(); // End JSON Object
        generator.close();
    }
}

আউটপুট (output.json):

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

2. Tree Model

Tree Model কী?

Tree Model JSON ডেটাকে একটি JsonNode ট্রি হিসেবে লোড করে। এটি ডাইনামিক এবং লো-লেভেল JSON ডেটা ম্যানিপুলেট করতে ব্যবহৃত হয়।

কেন ব্যবহার করবেন?

  • JSON ডেটা পরিবর্তন বা বিশ্লেষণ করতে।
  • কাঠামোবিহীন বা ডাইনামিক JSON হ্যান্ডল করতে।
  • Nested JSON ডেটা ম্যানিপুলেট করতে।

2.1 JSON Parsing (Reading)

Tree Model এর মাধ্যমে JSON ডেটা একটি JsonNode-এ লোড করে পড়া যায়।

উদাহরণ: JSON Parsing

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class TreeModelReadExample {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(new File("data.json"));

        String name = rootNode.get("name").asText();
        int age = rootNode.get("age").asInt();
        String city = rootNode.get("city").asText();

        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("City: " + city);
    }
}

JSON ইনপুট (data.json):

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

আউটপুট:

Name: John
Age: 30
City: Dhaka

2.2 JSON Writing

Tree Model ব্যবহার করে একটি নতুন JSON তৈরি করা যায়।

উদাহরণ: JSON Writing

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.File;
import java.io.IOException;

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

        // Create a root node
        ObjectNode rootNode = mapper.createObjectNode();
        rootNode.put("name", "John");
        rootNode.put("age", 30);
        rootNode.put("city", "Dhaka");

        // Write to JSON file
        mapper.writeValue(new File("output.json"), rootNode);
    }
}

আউটপুট (output.json):

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

2.3 Nested JSON Manipulation

Tree Model ব্যবহার করে Nested JSON ডেটা ম্যানিপুলেট করা যায়।

উদাহরণ: Nested JSON ম্যানিপুলেশন

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.File;
import java.io.IOException;

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

        // Parse JSON file
        JsonNode rootNode = mapper.readTree(new File("nested.json"));

        // Access nested fields
        JsonNode addressNode = rootNode.get("address");
        String street = addressNode.get("street").asText();
        System.out.println("Street: " + street);

        // Modify nested field
        ((ObjectNode) addressNode).put("city", "Chittagong");
        mapper.writeValue(new File("modified.json"), rootNode);
    }
}

JSON ইনপুট (nested.json):

{
  "name": "John",
  "address": {
    "street": "123 Main St",
    "city": "Dhaka"
  }
}

আউটপুট (modified.json):

{
  "name": "John",
  "address": {
    "street": "123 Main St",
    "city": "Chittagong"
  }
}

3. পার্থক্য: Streaming API vs Tree Model

FeatureStreaming APITree Model
PerformanceHigh (memory-efficient)Medium (uses more memory)
Use CaseLarge or simple JSONComplex or nested JSON
FlexibilityLow (linear parsing)High (easy manipulation)
Dynamic StructureNoYes
Ease of UseModerate (low-level control needed)High (node-based manipulation)

  • Streaming API: বড় JSON ফাইলের জন্য বা মেমরি অপ্টিমাইজেশনের প্রয়োজনে।
  • Tree Model: Nested বা কাঠামোবিহীন JSON ম্যানিপুলেশনের জন্য।
Content added By
Promotion

Are you sure to start over?

Loading...