Java serialization and deserialization process
Let’s break down what happens internally when you call:
Person p = mapper.readValue(json, Person.class);
and how a plain string (JSON) becomes a Java object.
🧩 Step-by-step Explanation (Inside ObjectMapper.readValue())
1️⃣ You call readValue(json, Person.class)
ObjectMapperis from Jackson (FasterXML).- You’re saying: “Hey Jackson, take this JSON string and turn it into a
Personobject.”
2️⃣ Jackson detects the data format
ObjectMapperchecks the input type (String → JSON text).- It picks a JsonParser (a Jackson internal streaming parser) to read the JSON token by token.
JsonParser parser = objectMapper.createParser(json);
3️⃣ JSON is parsed into tokens
Jackson doesn’t first build a big intermediate object — instead, it streams tokens like:
Example JSON:
{ "name": "Sagar", "age": 30 }
Jackson converts this into a stream of tokens:
START_OBJECT
FIELD_NAME "name"
VALUE_STRING "Sagar"
FIELD_NAME "age"
VALUE_NUMBER_INT 30
END_OBJECT
So it’s reading sequentially, like a tokenizer.
4️⃣ Jackson determines what type to build
-
It sees
Person.classand uses Java Reflection to understand its fields:class Person { private String name; private int age; // getters/setters } -
It creates a BeanDeserializer for
Person.
This deserializer knows how to:
- Create an instance of
Person - Call
setName()when the JSON key is"name" - Call
setAge()when the JSON key is"age"
5️⃣ Object instantiation
Jackson creates an empty object — usually using:
- The default constructor (
new Person()), or - For advanced cases, it can even use Unsafe.allocateInstance() (without calling the constructor).
6️⃣ Field mapping
As the parser reads each token:
"name"→ Jackson looks for a matching property (setName()or fieldname)"age"→ matchessetAge()or fieldage
Then Jackson uses Reflection or MethodHandles to assign the values:
person.setName("Sagar");
person.setAge(30);
7️⃣ Type conversion
If the field type doesn’t directly match (e.g., JSON "30" string to int),
Jackson automatically performs type coercion using DeserializationFeature rules.
Example:
{ "age": "30" } // string → int
Still maps correctly, because Jackson handles type conversion.
8️⃣ Return the populated object
Once all fields are processed and the END_OBJECT token is read,
Jackson returns the fully constructed and populated Person object.
return person;
🧠 In short, internally:
- Tokenize JSON text
- Identify class metadata via Reflection
- Create object instance
- Map JSON fields → Java fields
- Type convert if needed
- Return populated object
🧩 Bonus: Reverse process — writeValueAsString(person)
When you serialize:
String json = mapper.writeValueAsString(person);
Jackson:
- Uses Reflection to inspect getters.
- Converts them into key-value pairs.
- Writes them out as a JSON string using a
JsonGenerator.
🔬 Internals summary
| Step | Internal Component | Description |
|---|---|---|
| Parsing | JsonParser | Reads raw JSON as tokens |
| Mapping | BeanDeserializer | Maps tokens to Java fields |
| Reflection | JavaType, AnnotatedClass | Reads field/method metadata |
| Object creation | Constructor / Unsafe | Creates object instance |
| Conversion | DeserializationContext | Handles type coercion |
| Output | Returns fully hydrated object | ✅ |
💡 Interview Tip
If they ask:
“How does Jackson convert JSON to Java objects internally?”
✅ Answer (summary version):
Jackson uses a streaming parser (
JsonParser) to read JSON into tokens, then uses reflection-based deserializers (BeanDeserializer) to create an instance of the target class. It matches JSON fields to Java properties, sets values using reflection, performs type conversion when needed, and finally returns the populated object.