Guide
Java records for Jackson from a JSON sample
Data transfer objects are the plumbing of every Java service that talks to another API. Since Java 16, records make them short: one line declares the fields, the constructor, the accessors, equals, hashCode and toString. This generator turns a JSON sample into records ready for Jackson, the JSON library behind Spring Boot.
Why records
A record such as public record Item(String sku, Long qty) {} replaces dozens of lines of getters and constructor boilerplate, and its immutability suits data received from elsewhere. Jackson has supported records since version 2.12, and Spring Boot 2.5 and later ship a compatible version, so RestClient, WebClient and RestTemplate can deserialise into them directly.
Names and @JsonProperty
Java components are camelCase. When a JSON key already is, it is used as is; otherwise the component is renamed and annotated: @JsonProperty("order_id") Long orderId. Keys that are Java keywords, such as class or default, get a Value suffix plus the annotation. Every record also gets @JsonIgnoreProperties(ignoreUnknown = true), so a field the API adds later does not break deserialisation.
Boxed types on purpose
Numbers are Long and Double, and booleans Boolean, rather than the primitives. A primitive cannot hold null, and a missing key would silently become 0 or false; with boxed types, absent and null values stay null so your code can tell. Arrays become List<T>, and values whose type varies between samples become Object.
Dates
Switch on date types and ISO 8601 timestamps become OffsetDateTime, keeping the time-zone offset from the string. Jackson needs the Java time module for these, which Spring Boot registers for you.
Using the records
With a plain ObjectMapper: User user = mapper.readValue(json, User.class);. In Spring: restClient.get().uri(url).retrieve().body(User.class). For a JSON array at the root, read into List<User> with a TypeReference.
A worked example
The sample user produces User, Order, Item and Address records. The order_id key becomes @JsonProperty("order_id") Long orderId, is_admin becomes isAdmin, and the tags array becomes List<String> tags. Because the sample’s total includes a decimal, total is a Double.
When records do not fit
Records need Java 16 or later. For older codebases, turn each record into a class with private final fields, a constructor annotated @JsonCreator and getters, or add Lombok’s @Value. If you need mutable objects for a framework such as JPA, write ordinary classes instead; records are not entities.
Testing the mapping
Keep one real response as a test resource and write a small test that reads it into the root record and checks a few values. When the provider changes a type or renames a key, that test fails in your build instead of in production. Jackson’s FAIL_ON_UNKNOWN_PROPERTIES stays off thanks to the annotation, so additions never break it.
Arrays and wrapped responses
Many APIs wrap results, as in {"data": [...], "page": 2}. Paste the whole response: the wrapper becomes the root record and the items get their own record, so paging fields are typed too.
Records with Kotlin or Groovy callers
Records are ordinary Java types to other JVM languages: Kotlin sees the components as properties and Groovy as getters, so a shared model module can serve all of them without changes.
Related tools
Create the same models in Kotlin with JSON to Kotlin or for .NET with JSON to C#, turn a curl example into Java HttpClient code with cURL to Code, or tidy the sample in the JSON Formatter.
Checked against the current version of the JSON to Java Record on .

