Skip to content
Code2026-08-285 min read

How to Convert JSON to Java Entity Class (with annotations and List nesting)

Integrating an API returns JSON; you need the matching Java entity class (POJO). Hand-writing dozens of fields + getters/setters + annotations is tedious and error-prone. Can you auto-convert?

Yes. Here are the type-mapping rules and annotation choices for JSON → Java, and how to generate step by step.

JSON type to Java type mapping

JSON typeJava typeNotes
Object {}nested class / Map<String,Object>
Array []List<T>Prefer List over array
String "a"String
IntegerLong / IntegerLarge numbers → Long (avoid overflow)
DecimalDouble / BigDecimalMoney → BigDecimal
BooleanBoolean
nullwrapper type (e.g. Integer)Distinguish null from 0
Mixed arrayList<Object>Avoid if possible

Which serialization annotation

Three common Java JSON libraries, different annotations:

LibraryAnnotationExample
Jackson@JsonProperty("name")Mainstream, Spring default
Gson@SerializedName("name")Common in Android
Nativefield name must match JSONNot recommended

Spring Boot defaults to Jackson—examples below use it.

Step-by-step generation (no plugin)

Use this site's JSON to Java tool—runs locally, JSON never uploaded:

  1. Open JSON to Java.
  2. Paste JSON (object or array).
  3. Configure:
    • Root class name (e.g. User, OrderResponse);
    • Package (e.g. com.example.dto) — emitted as a package …; line when set;
    • Generate Lombok @Data (skip getters/setters);
    • Annotation style: none, Jackson @JsonProperty, or Gson @SerializedName.
  4. Output updates as you edit—copy the Java classes into the project.
  5. Need other languages? Use JSON to Go or JSON to TypeScript.

Full example

Input JSON:

{
  "id": 1024,
  "name": "Alice",
  "vip": true,
  "tags": ["java", "api"],
  "address": {
    "city": "Shanghai",
    "zip": "200000"
  }
}

Generated Java (Jackson + Lombok):

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;

@Data
public class User {
    @JsonProperty("id")
    private Long id;
    @JsonProperty("name")
    private String name;
    @JsonProperty("vip")
    private Boolean vip;
    @JsonProperty("tags")
    private List<String> tags;
    @JsonProperty("address")
    private Address address;
}

@Data
public class Address {
    @JsonProperty("city")
    private String city;
    @JsonProperty("zip")
    private String zip;
}

Advanced tips

  • Money → BigDecimal: double has precision issues; always use BigDecimal for currency.
  • Large integers → Long: JSON numbers beyond int range (2.1B) overflow.
  • Format first: tidy messy JSON with the JSON formatter for better inference.
  • null vs zero: use wrapper classes (Integer not int) so you can tell if a field was returned.
  • Time fields: JSON times are usually strings; use String or LocalDateTime + custom deserializer.

The Java-specific traps: dates, generics, optionals

Dates: generated POJOs map timestamp strings to String by default — switching to OffsetDateTime or Instant changes the deserializer requirements (Jackson needs JavaTimeModule registered; Gson needs its own adapter). Epoch-milliseconds fields (createdAt: 1699012345678) map to long, silently losing timezone information — a review of "which fields are epoch, which are ISO strings" belongs in every schema import. Generics: List<OrderItem> erases at runtime — a JSON array of heterogeneous objects deserializes without error into a list whose elements fail at first cast. Optional: Optional<T> in field positions is discouraged by the language authors themselves (Optional was designed for return types); nullable object fields with null-checks, or @Nullable annotations, are the Java-idiomatic representation of absent JSON keys.

Records: the 2021+ answer nobody's converter defaults to

Java records (record User(String id, String name) {}) give immutable data classes with generated equals/hashCode/toString in one line — exactly what JSON POJOs want. Most generators still emit old-style classes with private fields and sixty lines of getters/setters because records require Java 16+. If your project is on a modern JDK, converting generated output to records is a mechanical five-minute cleanup that pays forever: immutability for free in concurrent code, and Jackson/Gson both support records natively now. The one trade: records are final — no inheritance hierarchies, which for API DTOs is almost always the right constraint anyway.

Unknown fields and strictness

A JSON response that grows a new field breaks strict deserializers (UnrecognizedPropertyException in Jackson's default configuration) — the classic production incident when an upstream API adds a key at 2am. The three postures: ignore unknowns (@JsonIgnoreProperties(ignoreUnknown = true) — resilient, the default choice for API clients), fail-fast (keep the exception for internal contracts where silent schema drift is worse), or capture (@JsonAnyGetter/@JsonAnySetter into a map — for audit/echo scenarios). Decide per boundary, write it down, and make the generated code carry the annotation rather than relying on a global ObjectMapper configuration that the next service silently misses.

Primitive vs wrapper inference

Generators often emit int / long / boolean from non-null sample values. That is fine until a later payload sends null for the same key — then deserialization fails or boxes unexpectedly. Prefer wrappers (Integer, Long, Boolean) at API boundaries unless the contract documents the field as always present. Large integers beyond Number.MAX_SAFE_INTEGER should stay on a lossless path into long (or BigInteger when they exceed 64-bit); money fields still want BigDecimal even when the sample looks like a plain float.

FAQ

Q: Array elements inconsistent types? Use List<Object> and judge yourself; or push the API to unify structure.

Q: Field is snake_case user_name, Java wants camelCase? Map with @JsonProperty("user_name"); write the Java field as userName.

Q: Use Lombok? If the team standardizes on it, it cuts boilerplate massively; if banned, the tool can emit plain getters/setters.

Q: List or array? Prefer List<T>—more flexible for dynamic length; use arrays only for specific perf/interop needs.

Summary

JSON to Java POJO = generate annotated classes by type mapping; money → BigDecimal, large numbers → Long, null → wrapper. Use this site's JSON to Java tool to generate locally—JSON not uploaded, safer for sensitive payloads.

Implementation notes

Two scars from this site's type generator are worth recording: heterogeneous arrays once silently dropped everything after the first element, and the fix now emits a union element type named after the singularized key; keys with no usable word characters fall back to a safe placeholder name during PascalCase conversion instead of producing an illegal identifier. The same caution applies to your samples — for a field whose array mixes numbers and strings, don't feed the generator only the first record.