100% local — your data never leaves your browser

JSON to Java — Records Jackson Can Decode

Turn a JSON sample into Java records. Boxed types and a Jackson annotation wherever a name had to differ, so the payload decodes as written.

Instant Private Zero cookies

JSON input

Java output

What this tool does

A JSON sample becomes Java records, one per object.

{ "id": 1, "firstName": "Ada", "address": { "city": "Paris" } }
public record Root(
    Long id,
    String firstName,
    Address address
) {}

public record Address(
    String city
) {}

Records are the shortest way to express “data and nothing else” in modern Java — a constructor, accessors, equals, hashCode and toString come with them. They need Java 16 or later.

The key survives the rename

A component name follows Java’s rules: no dash, no leading digit, no keyword. content-type becomes contentType, class becomes class_, 2fa becomes f2fa. Each time the name has to change, the original key rides along:

import com.fasterxml.jackson.annotation.JsonProperty;

public record Root(
    @JsonProperty("content-type") String contentType,
    @JsonProperty("class") Long class_,
    Boolean ok
) {}

Without that annotation Jackson looks for contentType and finds nothing — the record no longer reads the document it was generated from. It was missing until this page was written; the defect is fixed, and the annotation appears only where the name actually changed, with its import.

Boxed types, and why

Every number is a Long or a Double, every boolean a Boolean. JSON has null, Java primitives do not, and a double receiving a null becomes 0.0 — a value you cannot tell from a real zero. The boxed types keep null representable, which is what the format allows.

For the same reason null and unknown values become Object, and an array of them a List<Object>.

What a sample cannot say

Nothing is optional and nothing is annotated @Nullable: every component is there because the document had it. Records are shallowly immutable, so a field you later decide can be absent is a change of shape, not a flag.

A scalar at the root — 42, "text" — is refused: Java has no type alias, so there is nothing to name. A JSON array of objects gives you the record of its element, which is the shape you actually bind to a List<Root>.

Private by design

Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.

Frequently asked questions

Why `Long` and `Double` rather than `long` and `double`?
Because a JSON field can be null, and a primitive cannot. Decoding `{"score": null}` into a `double` either throws or silently gives 0.0, depending on the library and its settings. The boxed types make the absence representable — and they are also what generics require if the value ever lands in a `List`.
Where does the `@JsonProperty` come from?
From the key not surviving the trip. `content-type` cannot be a component name, so it becomes `contentType` — and Jackson then looks for `contentType` in the JSON and finds nothing. The annotation pins the original key. It used to be missing: the record stopped reading the document it came from, silently. That was a real defect, fixed.
I use Gson, not Jackson. What changes?
The annotation. Gson wants `@SerializedName("content-type")` in the same place, and JSON-B wants `@JsonbProperty`. The component names and types are identical either way — a search and replace on the annotation and its import is the whole adaptation.

Related converters