DEV Community

Datawharf Tools
Datawharf Tools

Posted on

Paste JSON, get Java records: a small IntelliJ plugin for API payloads

If you write Java against REST APIs, you have typed the same thing many times: copy a JSON response, then hand-write the classes that match it. For years the IntelliJ answer was GsonFormat, which generated old-style POJOs. It stopped working with current IDEs a while ago, and the popular JSON-to-class plugins I checked generate classes, not Java records, which is what you want for an immutable API payload in Java 16+.

So I built a small one: JSON to Java Record, now on the JetBrains Marketplace.

What it does

Copy this JSON:

{
  "order_id": 10452,
  "created_at": "2026-11-08T14:03:00Z",
  "total": 129.95,
  "paid": true,
  "customer": { "id": 88, "full_name": "Ana Ruiz", "email": "ana@example.com" },
  "items": [
    { "sku": "KB-01", "qty": 1, "price": 89.0 },
    { "sku": "MS-02", "qty": 2, "price": 20.475, "gift_wrap": true }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Press Alt+Insert in a Java file, choose Paste JSON as Java Record... (also under Tools), name it Order, and you get this (the plugin's actual output; in the editor it is then reformatted with your own code style):

import java.util.List;

public record Order(
    int orderId,
    String createdAt,
    double total,
    boolean paid,
    Customer customer,
    List<Item> items
) {
    public record Customer(
        int id,
        String fullName,
        String email
    ) {}

    public record Item(
        String sku,
        int qty,
        double price,
        Boolean giftWrap
    ) {}
}
Enter fullscreen mode Exit fullscreen mode

A few details that matter in real payloads:

  • Nested objects become nested records, and arrays of objects become List<...> of a record.
  • Arrays are merged. gift_wrap appears in only one of the two items, so it becomes a boxed Boolean (it can be null), while fields present everywhere stay primitive.
  • Numbers are typed sensibly: int, long for big values, double for decimals; a list mixing 1 and 2.5 becomes List<Double>.
  • snake_case becomes camelCase, and reserved words are made safe (class becomes class_).

Keep the original JSON names

If your mapper needs the original keys, pick Jackson or Gson in the dialog. Only the fields whose Java name differs get an annotation:

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

public record Order(
    @JsonProperty("order_id") int orderId,
    @JsonProperty("created_at") String createdAt,
    double total,
    boolean paid,
    Customer customer,
    List<Item> items
) {
    public record Customer(
        int id,
        @JsonProperty("full_name") String fullName,
        String email
    ) {}

    public record Item(
        String sku,
        int qty,
        double price,
        @JsonProperty("gift_wrap") Boolean giftWrap
    ) {}
}
Enter fullscreen mode Exit fullscreen mode

Gson users get @SerializedName instead.

Where it puts the code

  • In an open Java file, it inserts at the caret (or replaces a selection), adds missing imports at the top and reformats.
  • From the Project view (right-click a package, New > Paste JSON as Java Record...), it creates Order.java there. It never overwrites an existing file.
  • Invalid JSON shows an error and changes nothing. It reads your clipboard, works offline and sends no telemetry.

Limits, honestly

  • IntelliJ IDEA 2025.2 or newer, with Java support. It does not run in PyCharm or WebStorm.
  • Types are inferred from the sample you paste. A field that is null in your sample becomes Object; paste a fuller sample or fix that one type by hand.
  • Dates stay String. Mapping them to Instant or LocalDate is your call.

Get it

It is a first version. If it gets a type wrong on your payload, or you want another output (Lombok, Kotlin data classes, TypeScript), open an issue or tell me in the comments.

Top comments (0)