JSON & Serialization — Jackson, Gson
Java object ↔ JSON — আধুনিক serialization
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.
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.
Serializable binary blob তৈরি করে যেটি শুধু Java পড়তে পারে। Production-এ এটি এড়িয়ে চলা হয় — বহু security CVE, version-mismatch সমস্যা এবং JVM-এর বাইরে কেউ পড়তে পারে না। সবসময় JSON ব্যবহার করুন।
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.
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:
jackson-databind dependency যোগ করুন, তারপর ObjectMapper class পাবেন। দুটি main method — writeValueAsString (object → JSON) ও readValue (JSON → object)।
// 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:
| Annotation | Purpose | বাংলায় |
|---|---|---|
@JsonProperty("full_name") | Map a Java field to a different JSON key. | JSON-এর key আলাদা নামে মাপিং। |
@JsonIgnore | Skip 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 constructor | Deserialize into immutable records. | immutable record-এ পড়তে। |
@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:
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.
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
| Term | Meaning | বাংলায় |
|---|---|---|
| Serialization | Turning a live object into a string / byte stream. | object → text/bytes রূপান্তর। |
| Deserialization | Turning bytes back into an object. | bytes → object ফিরিয়ে আনা। |
| ObjectMapper | The central Jackson class for JSON conversion. | Jackson-এর main class। |
| POJO | Plain Old Java Object — a simple data-holder class. | সাধারণ data holder class। |
| DTO | Data Transfer Object — a POJO shaped for wire transport. | wire-transport-এর জন্য তৈরি POJO। |
| @JsonProperty | Renames a field during JSON mapping. | JSON-এ key rename। |
9. Practice Problems
-
Write a
Productrecord withname,price,stock, then manually print its JSON.একটিProductrecord লিখুন —name,price,stock— তারপর manually JSON print করুন।Show Answer (উত্তর দেখুন)
Main.javaclass 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); } } -
Explain in 2 sentences when you would use
@JsonIgnore.দুই বাক্যে বলুন — কখন@JsonIgnoreব্যবহার করবেন।Show Answer (উত্তর দেখুন)
Answer: Use
@JsonIgnoreto 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 থামায়। -
Produce a JSON array of three student records using streams.stream দিয়ে তিনজন ছাত্রের JSON array তৈরি করুন।
Show Answer (উত্তর দেখুন)
Main.javaimport 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); } } -
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 হয় না।
-
Produce JSON for a nested object — an
Ordercontaining a list ofItems.একটি nested JSON তৈরি করুন —Order-এর ভেতরেItem-এর list।Show Answer (উত্তর দেখুন)
Main.javaimport 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.
Serializable এড়িয়ে চলুন — ধীর, অনিরাপদ, JVM-এর বাইরে পড়া যায় না।