JSON with Jackson
Jackson is Java's standard JSON library and is built into Spring Boot, so @RestController methods turn objects into JSON automatically.
With an ObjectMapper (Spring Boot 4 uses Jackson 3's JsonMapper, with the same ideas):
writeValueAsString(obj): Java to JSON (serialisation)readValue(json, Order.class): JSON to Java (deserialisation)readValue(json, new TypeReference<List<Order>>() {})for generic typesreadTree(json)to walk JSON you don't have a class for
Records work out of the box. Common annotations:
@JsonProperty("order_id")maps a different JSON name.@JsonIgnorehides a field (passwords, internal notes).@JsonIgnoreProperties(ignoreUnknown = true)tolerates extra fields from other APIs.@JsonFormatcontrols date formats.
Create one ObjectMapper, configure it and reuse it: it's thread-safe and costly to build.
Example
public record Order(
@JsonProperty("order_id") String id,
String customer,
BigDecimal amount,
LocalDate placedOn,
@JsonIgnore String internalNote) {}
ObjectMapper mapper = JsonMapper.builder()
.addModule(new JavaTimeModule()) // Jackson 2: java.time support
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build();
String json = mapper.writeValueAsString(
new Order("ORD-7", "Asha", new BigDecimal("1499.00"), LocalDate.of(2026, 9, 24), "vip"));
// {"order_id":"ORD-7","customer":"Asha","amount":1499.00,"placedOn":"2026-09-24"}
Order back = mapper.readValue(json, Order.class);
List<Order> many = mapper.readValue("[" + json + "]", new TypeReference<List<Order>>() {});
JsonNode node = mapper.readTree("{\"user\":{\"name\":\"Ravi\",\"tags\":[\"java\",\"spring\"]}}");
String name = node.path("user").path("name").asText(); // RaviCommon mistake
Creating a new ObjectMapper for every request. It's thread-safe and costly to build; configure one and reuse it, or inject Spring's.
Under the hood
Never deserialise untrusted JSON into polymorphic types with default typing turned on; it has caused remote-code-execution vulnerabilities. Keep API classes (DTOs) separate from JPA entities so lazy associations and internal fields never leak into responses. Jackson 3 (used by Spring Boot 4) moved to the tools.jackson package, supports java.time by default and uses unchecked exceptions, while the annotations keep their old package.
Check yourself
Which annotation keeps a field out of the JSON?
How this connects
Know these first
Where this leads
Part of Job-ready backend developer, Upgrade from Java 8 to Java 25.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.