Deserializing JSON in Java and Kotlin
When you call a REST API in Java or Kotlin, the response comes back as a JSON string. To work with it in a type-safe way, you need model classes that match the JSON structure. Jackson, the de-facto JSON library for the JVM, deserializes the string into your objects automatically once you define those classes.
Writing these classes by hand for complex API responses is tedious. Use JSONKit's generators to produce them instantly: - JSON to Java POJO: /json-to-java - JSON to Kotlin Data Class: /json-to-kotlin
Java with Jackson
Given this JSON API response:
{
"user_id": 1,
"first_name": "Ravi",
"is_verified": true,
"address": {
"city": "Surat",
"pin_code": "395001"
}
}Jackson mode generates:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Address {
@JsonProperty("pin_code")
private String pinCode;
private String city;
public String getPinCode() { return pinCode; }
public void setPinCode(String pinCode) { this.pinCode = pinCode; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Root {
@JsonProperty("user_id")
private Long userId;
@JsonProperty("first_name")
private String firstName;
@JsonProperty("is_verified")
private Boolean isVerified;
private Address address;
// getters and setters...
}Deserialize it:
ObjectMapper mapper = new ObjectMapper();
Root user = mapper.readValue(jsonString, Root.class);
System.out.println(user.getFirstName()); // RaviJava with Lombok
Lombok eliminates the getters/setters boilerplate. Add the Lombok dependency and use @Data:
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Root {
@JsonProperty("user_id")
private Long userId;
@JsonProperty("first_name")
private String firstName;
@JsonProperty("is_verified")
private Boolean isVerified;
private Address address;
}Lombok generates all getters, setters, equals(), hashCode(), and toString() at compile time. No IDE plugin needed for it to work at runtime.
Kotlin Data Class
Kotlin's data class is even cleaner — it handles all boilerplate natively:
import com.fasterxml.jackson.annotation.JsonProperty
data class Address(
val city: String,
@JsonProperty("pin_code") val pinCode: String
)
data class Root(
@JsonProperty("user_id") val userId: Long,
@JsonProperty("first_name") val firstName: String,
@JsonProperty("is_verified") val isVerified: Boolean,
val address: Address
)Deserialize with Kotlin Jackson module:
val mapper = ObjectMapper().registerModule(KotlinModule.Builder().build())
val user: Root = mapper.readValue(jsonString)
println(user.firstName) // RaviSpring Boot — Zero Config
In Spring Boot, Jackson is auto-configured. You can inject ObjectMapper directly or use the RestTemplate / WebClient which deserialize automatically:
// WebClient (reactive)
val user = webClient.get()
.uri("/users/1")
.retrieve()
.bodyToMono<Root>()
.awaitFirst()
// RestTemplate
val user = restTemplate.getForObject("/users/1", Root::class.java)Type Mapping Reference
| JSON | Java | Kotlin |
|---|---|---|
| string | String | String |
| integer | Long | Long |
| float | Double | Double |
| boolean | Boolean | Boolean |
| null | Object | Any? |
| array | List<T> | List<T> |
| object | Class | data class |
Pro Tips
- Always add
@JsonIgnoreProperties(ignoreUnknown = true)so your classes survive API additions without breaking. - Use
Longnotintfor IDs — APIs sometimes return large integers that overflow 32-bit integers. - For dates, use
Stringin the model class and parse withLocalDateTime.parse()— Jackson's@JsonFormatcan do it automatically but requires configuring the mapper.