JSON & Serialization — Jackson, Gson

Java object ↔ JSON — আধুনিক serialization

Read: ~28 min Intermediate 5 practice problems Live code runner

1. Why JSON Runs the World

Every modern API speaks JSON — a simple, text-based format invented for JavaScript that every language now understands. When a Dhaka payment gateway talks to a Dutch bank, they do not send raw Java objects — they send JSON. Your job as a Java developer is to convert between your domain objects (User, Order, Payment) and the JSON bytes that flow over the network.

আধুনিক প্রতিটি API JSON ভাষায় কথা বলে — JavaScript-এর জন্য তৈরি একটি simple text-format, এখন সব ভাষা বোঝে। ঢাকার payment gateway যখন ডাচ ব্যাংকের সাথে কথা বলে, তারা raw Java object পাঠায় না — JSON পাঠায়। Java developer হিসেবে আপনার কাজ — domain object (User, Order) এবং network-এ যাওয়া JSON bytes-এর মধ্যে convert করা।

The two serious JSON libraries in Java are Jackson (industry default, used by Spring Boot) and Gson (Google, popular on Android). Both do the same thing; Jackson is richer and faster on big payloads, Gson is smaller and simpler.

2. Why Not Java's Built-in Serializable?

Java has had java.io.Serializable since 1997. It produces a binary blob that only Java can read. In modern production code it is avoided: it has been the source of many security CVEs, it tightly couples serialized bytes to the exact class definition, and nothing outside the JVM can read it. Use JSON instead.

Java-র পুরনো Serializable binary blob তৈরি করে যেটি শুধু Java পড়তে পারে। Production-এ এটি এড়িয়ে চলা হয় — বহু security CVE, version-mismatch সমস্যা এবং JVM-এর বাইরে কেউ পড়তে পারে না। সবসময় JSON ব্যবহার করুন।
Java object ⇄ JSON — the round trip User object name="Raihan" age=24 (in JVM RAM) writeValueAsString JSON text {"name":"Raihan", "age":24} (string on wire) readValue User object name="Raihan" age=24 (reconstructed) Figure 33.1 — Jackson-এর ObjectMapper দুই দিকেই কাজ করে।

3. A JSON Round Trip — Hand-Written

The Wandbox sandbox in this course does not have Maven, so we cannot import Jackson here — but the logic is identical. Below is a tiny hand-written JSON writer and a parser you can run live. In a real project you would replace all of this with two lines of Jackson.

এই sandbox-এ Maven নেই, তাই Jackson import করা যাবে না — কিন্তু concept একই। নিচে একটি ছোট hand-written JSON writer এবং parser দিলাম যেটা live রান করবে। বাস্তব project-এ Jackson-এর দুটি লাইনেই পুরো কাজ হয়ে যাবে।
Main.java
class Main {
    static class User {
        String name;
        int age;
        User(String n, int a) { name = n; age = a; }
        String toJson() {
            return "{\"name\":\"" + name + "\",\"age\":" + age + "}";
        }
    }

    public static void main(String[] args) {
        User u = new User("Raihan", 24);
        String json = u.toJson();
        System.out.println("JSON  = " + json);

        // parse back (toy version — extract age between `:` and `}`)
        int idx = json.indexOf("age\":") + 5;
        int end = json.indexOf("}", idx);
        int age = Integer.parseInt(json.substring(idx, end));
        System.out.println("parsed age = " + age);
    }
}

4. The Real Jackson API (in your Maven project)

Add Jackson to your pom.xml — com.fasterxml.jackson.core:jackson-databind — and you get the ObjectMapper. Two methods, and you are done:

বাস্তব Maven project-এ jackson-databind dependency যোগ করুন, তারপর ObjectMapper class পাবেন। দুটি main method — writeValueAsString (object → JSON) ও readValue (JSON → object)।
Main.java (Jackson — needs Maven)
// This snippet shows real Jackson usage.
// It will NOT run in the sandbox (no Jackson jar).
// Add to pom.xml:
//   <dependency><groupId>com.fasterxml.jackson.core</groupId>
//     <artifactId>jackson-databind</artifactId>
//     <version>2.17.0</version></dependency>

import com.fasterxml.jackson.databind.ObjectMapper;

class Main {
    static class User {
        public String name;
        public int age;
        public User() {}
        public User(String n, int a) { name = n; age = a; }
    }

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

        // object -> JSON
        String json = m.writeValueAsString(new User("Raihan", 24));

        // JSON -> object
        User back = m.readValue(json, User.class);

        System.out.println(json);
        System.out.println(back.name + " / " + back.age);
    }
}

5. Jackson Annotations You Will Actually Use

Real-world JSON rarely matches your Java field names exactly. These four annotations cover 90% of what you need:

বাস্তব JSON কখনোই Java field-এর নামের সাথে exact match করে না। নিচের ৪টি annotation-ই ৯০% কাজ করবে।
AnnotationPurposeবাংলায়
@JsonProperty("full_name")Map a Java field to a different JSON key.JSON-এর key আলাদা নামে মাপিং।
@JsonIgnoreSkip a field during serialization (e.g., password).serialization-এ বাদ (যেমন password)।
@JsonFormat(pattern = "yyyy-MM-dd")Format dates / numbers.date/number এর format।
@JsonInclude(NON_NULL)Omit null fields from output.null field output-এ বাদ।
@JsonCreator / @JsonProperty on constructorDeserialize into immutable records.immutable record-এ পড়তে।
In Spring Boot you get Jackson "for free" — return any Java object from a @RestController and Spring auto-converts to JSON. This is 99% of modern Java backend work.

6. Gson — Google's Simpler Alternative

Gson has a smaller API and is popular on Android. Two lines give you a round trip:

Gson ছোট API, Android-এ জনপ্রিয়। Jackson-এর চেয়ে কম feature, কিন্তু simple কাজে যথেষ্ট।
Main.java (Gson — needs Maven)
import com.google.gson.Gson;

class Main {
    static class User {
        String name; int age;
        User(String n, int a) { name = n; age = a; }
    }
    public static void main(String[] args) {
        Gson g = new Gson();
        String json = g.toJson(new User("Nusrat", 22));
        User u = g.fromJson(json, User.class);
        System.out.println(json);
        System.out.println(u.name + " / " + u.age);
    }
}

Jackson (Spring Boot default)

  • Faster on large JSON
  • Richer annotation set
  • Streaming API (JsonParser)
  • Spring Boot & Kafka default

Gson (Google, Android)

  • Smaller jar
  • Simpler API
  • Android-friendly
  • Fewer advanced features

7. Hand-Rolled List-of-Objects to JSON (Runnable)

To make this lecture feel real inside the sandbox, here is a runnable example that builds JSON for a list of users without any external library. It demonstrates the exact structure Jackson would emit.

sandbox-এ Jackson নেই বলে নিচে library ছাড়াই list-of-user JSON বানাচ্ছি — ঠিক সেই format-এ যেটা Jackson তৈরি করবে।
Main.java
import java.util.*;
import java.util.stream.*;

class Main {
    record User(String name, int age) {
        String toJson() {
            return "{\"name\":\"" + name + "\",\"age\":" + age + "}";
        }
    }

    public static void main(String[] args) {
        List<User> users = List.of(
            new User("Raihan", 24),
            new User("Nusrat", 22),
            new User("Tariq", 30)
        );
        String json = users.stream()
            .map(User::toJson)
            .collect(Collectors.joining(",", "[", "]"));
        System.out.println(json);
    }
}

8. Vocabulary

TermMeaningবাংলায়
SerializationTurning a live object into a string / byte stream.object → text/bytes রূপান্তর।
DeserializationTurning bytes back into an object.bytes → object ফিরিয়ে আনা।
ObjectMapperThe central Jackson class for JSON conversion.Jackson-এর main class।
POJOPlain Old Java Object — a simple data-holder class.সাধারণ data holder class।
DTOData Transfer Object — a POJO shaped for wire transport.wire-transport-এর জন্য তৈরি POJO।
@JsonPropertyRenames a field during JSON mapping.JSON-এ key rename।

9. Practice Problems

  1. Write a Product record with name, price, stock, then manually print its JSON.
    একটি Product record লিখুন — name, price, stock — তারপর manually JSON print করুন।
    Show Answer (উত্তর দেখুন)
    Main.java
    class Main {
        record Product(String name, double price, int stock) {}
        public static void main(String[] args) {
            Product p = new Product("Keyboard", 1499.0, 7);
            String json = "{\"name\":\"" + p.name() + "\",\"price\":" + p.price() + ",\"stock\":" + p.stock() + "}";
            System.out.println(json);
        }
    }
  2. Explain in 2 sentences when you would use @JsonIgnore.
    দুই বাক্যে বলুন — কখন @JsonIgnore ব্যবহার করবেন।
    Show Answer (উত্তর দেখুন)

    Answer: Use @JsonIgnore to keep sensitive or internal fields out of the JSON you ship to clients — passwords, hashes, database IDs, internal audit timestamps, lazy-loaded ORM relationships. It prevents accidental leaks and avoids infinite recursion in bidirectional entity graphs.

    password, hash, internal DB id, lazy-loaded ORM relationship — এসব field JSON-এ না পাঠানোর জন্য @JsonIgnore লাগান। security leak এড়ায়, এবং bidirectional entity-তে infinite recursion থামায়।

  3. Produce a JSON array of three student records using streams.
    stream দিয়ে তিনজন ছাত্রের JSON array তৈরি করুন।
    Show Answer (উত্তর দেখুন)
    Main.java
    import java.util.*;
    import java.util.stream.*;
    class Main {
        record Student(String id, String name) {
            String j() { return "{\"id\":\""+id+"\",\"name\":\""+name+"\"}"; }
        }
        public static void main(String[] args) {
            String json = Stream.of(
                    new Student("22-1", "Raihan"),
                    new Student("22-2", "Nusrat"),
                    new Student("22-3", "Tariq"))
                .map(Student::j).collect(Collectors.joining(",", "[", "]"));
            System.out.println(json);
        }
    }
  4. In 3 sentences, say why native Java Serialization is discouraged today.
    তিন বাক্যে বলুন — native Java Serialization কেন আজ discourage করা হয়।
    Show Answer (উত্তর দেখুন)

    Answer: Native Java Serialization has been the root cause of many high-severity CVEs — crafted bytes can trigger arbitrary code execution during deserialization. The binary format is unreadable outside Java, so no other language on the other end of an API can parse it. It also tightly couples the serialized bytes to the exact class structure, making version evolution painful.

    Native Java Serialization বহু high-severity CVE-র উৎস — crafted bytes deserialization-এ arbitrary code run করাতে পারে। Binary format Java-র বাইরে কেউ পড়তে পারে না। Class structure সামান্য বদলালেই বহু আগের serialized data আর read হয় না।

  5. Produce JSON for a nested object — an Order containing a list of Items.
    একটি nested JSON তৈরি করুন — Order-এর ভেতরে Item-এর list।
    Show Answer (উত্তর দেখুন)
    Main.java
    import java.util.*;
    import java.util.stream.*;
    class Main {
        record Item(String name, int qty) {
            String j() { return "{\"name\":\""+name+"\",\"qty\":"+qty+"}"; }
        }
        record Order(String id, List<Item> items) {
            String j() {
                String arr = items.stream().map(Item::j)
                    .collect(Collectors.joining(",", "[", "]"));
                return "{\"id\":\""+id+"\",\"items\":"+arr+"}";
            }
        }
        public static void main(String[] args) {
            Order o = new Order("A-1", List.of(
                new Item("Rice", 3), new Item("Oil", 1)));
            System.out.println(o.j());
        }
    }

Summary — Module 33

JSON is the wire format of the modern web. Java talks to it through Jackson (the Spring Boot default, rich and fast) or Gson (small and Android-friendly). Both reduce serialization to two calls — object to string, string to object. Avoid native Serializable: it is slow, insecure, and unreadable outside the JVM.

আধুনিক web-এর wire format JSON। Java-তে Jackson (Spring Boot default, দ্রুত ও rich) বা Gson (Android-friendly) ব্যবহার করুন। দুটি লাইনেই object ↔ JSON। Native Serializable এড়িয়ে চলুন — ধীর, অনিরাপদ, JVM-এর বাইরে পড়া যায় না।

Next Module → Date & Time API — java.time।