DevToolsmith

JSON to Java Class Converter

Paste JSON to generate Java records, Lombok classes or classic POJOs with getters and setters. Field names are converted to camelCase with Jackson @JsonProperty annotations, and nullable values use boxed types.

Runs 100% in your browser — nothing is uploaded

JSON
Tip: drop a file here361 chars · 361 bytes · 14 lines
Java classes
377 chars · 377 bytes · 18 lines

Tip: paste an array of several objects — keys missing from some of them become optional (boxed types).

Example

JSON input
{
  "order_id": 5012,
  "status": "paid",
  "customer": {
    "id": "c_88",
    "email": "lin@example.com"
  },
  "total": 59.9,
  "lines": [
    {
      "sku": "TSHIRT-M",
      "qty": 2
    },
    {
      "sku": "MUG",
      "qty": 1,
      "gift_note": "Happy birthday!"
    }
  ]
}
Generated Java (root name: Order)
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

public record Order(
    @JsonProperty("order_id") long orderId,
    String status,
    Customer customer,
    double total,
    List<Line> lines
) {
    public record Customer(String id, String email) {}

    public record Line(String sku, long qty, @JsonProperty("gift_note") String giftNote) {}
}
  • order_id became orderId with @JsonProperty("order_id"), so Jackson still maps it.
  • gift_note appears in only one line item, so it can be missing.
  • Identical object shapes share one type instead of being duplicated.

Parsing JSON with Jackson

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper mapper = new ObjectMapper();

// A single object
Order order = mapper.readValue(json, Order.class);
System.out.println(order.customer().email());

// A JSON array: generic types need a TypeReference
List<Order> orders = mapper.readValue(json, new TypeReference<List<Order>>() {});

// And back to JSON
String out = mapper.writeValueAsString(order);

With records, accessors have no get prefix: order.customer(), not order.getCustomer().

Type mapping

JSONJava
stringString (optionally OffsetDateTime, LocalDate or UUID)
integerlong, or Long when nullable
decimal numberdouble, or Double when nullable
true / falseboolean, or Boolean when nullable
objectnested record or static class
arrayList<T>
always null / mixed typesObject

Integers map to long because a JSON sample doesn’t tell you the range, and IDs and timestamps often exceed int’s 2,147,483,647. Change to int where you know values are small. For money, replace double with BigDecimal to avoid rounding errors.

Dates and java.time

With java.time and UUID types enabled, ISO 8601 timestamps become OffsetDateTime and dates become LocalDate. Jackson only understands these after registering the JSR-310 module:

// com.fasterxml.jackson.datatype:jackson-datatype-jsr310
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

Spring Boot registers it automatically. Generating for other languages? Try JSON to Kotlin, JSON to C# or JSON to Go.

Frequently asked questions

How do I convert JSON to a Java class?

Paste a JSON sample into the tool above. It creates a Java type for every object, picks the right Java types (String, long, double, boolean, List), converts keys to camelCase field names and adds @JsonProperty where the JSON key differs, so Jackson maps it correctly. Copy the result into a .java file named after the outer type.

Should I use records or classes?

Use records on Java 16 or newer: they are immutable, short, and supported by Jackson 2.12+ and Gson 2.10+. Choose Lombok if your project already uses it and you need mutable objects, or plain getters and setters for older Java versions and frameworks that require a no-argument constructor, such as some JPA setups.

Why are nested types inside the outer class?

A Java file can only contain one public top-level type, so the generator nests the others inside it. That way the result compiles as a single file. Nested records are implicitly static; nested classes are declared static so Jackson can create them. Move them to their own files if you prefer.

Why is a field Integer or Long instead of int or long?

Primitive types cannot be null. When a key is missing from some samples or is sometimes null, the generator uses the boxed type (Long, Double, Boolean) so the value can be null instead of silently becoming 0 or false.

Why does Jackson fail with “Unrecognized field”?

Jackson’s ObjectMapper rejects JSON keys that have no matching field by default. Add @JsonIgnoreProperties(ignoreUnknown = true) to the type, or configure mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false). Spring Boot already turns this check off.