How to Convert JSON to Java (Jackson POJOs, Done Right)
To read JSON in Java you need a class to bind it to, and writing those POJOs by hand is tedious: every field needs the right type, and every field whose name differs from the JSON key needs a Jackson annotation or it silently stays null. Generating the classes from a real sample fixes both. This guide covers how the mapping works, the fastest way to do it, and the Java-specific gotchas around annotations, boxed types, and List.
The fastest route: a browser generator
For a one-off, paste the JSON into the JSON to Java converter. It reads the sample, infers the type of every field, and writes classes ready for Jackson: nested objects become their own classes, arrays become List types, numbers resolve to Long or Double, and each field carries a @JsonProperty tag with the imports you need. Because it runs entirely in your browser, the JSON never leaves your machine, which matters when the sample is a real production response.
If the JSON will not convert, it is almost always invalid rather than genuinely unconvertible. Run it through the JSON parser to find the exact syntax error, or format it so you can see the structure first.
How JSON maps to Java
A generator makes the same decisions every time. Knowing them tells you what to expect.
- Objects become classes. Each object turns into a class, and each key becomes a field with a
@JsonPropertytag carrying the original key. - Nested objects get their own class. Rather than inlining a deep object, the generator names it and references it from the parent, which keeps the classes reusable.
- Arrays become
Listtypes.["a","b"]becomesList<String>; an array of objects becomesList<Item>with a generatedItemclass. - Numbers split into
LongandDouble. Whole numbers map toLong; anything with a decimal point maps toDouble.
Here is the shape of a simple conversion:
{ "id": 1, "name": "Ada", "tags": ["admin", "dev"] }
becomes:
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Root {
@JsonProperty("id")
public Long id;
@JsonProperty("name")
public String name;
@JsonProperty("tags")
public List<String> tags;
}
Why @JsonProperty matters
Jackson maps JSON keys to Java fields by name. When your field is userId but the JSON key is user_id, Jackson will not connect them unless you either configure a global naming strategy or annotate the field:
@JsonProperty("user_id")
public Long userId;
Without that, userId quietly stays null after deserialization, which is one of the most common “my object is empty” bugs in Java. Generation removes it: every field gets the correct tag automatically, so the class binds no matter how the keys are named.
Why boxed types, not primitives
The generator uses Long, Double, and Boolean rather than long, double, and boolean. The reason is null. A primitive long cannot be null, so if the JSON omits the field or sends null, Jackson has nowhere to put the absence and you get 0 instead, which is indistinguishable from a real zero. Boxed wrapper types can be null, so they represent JSON faithfully. For any field that might be absent, boxed is the safe default, and generated POJOs use it throughout.
When you see Object
A field that is only ever null, an empty array, or holds more than one unrelated type has no single concrete Java type, so it falls back to Object (or List<Object> for a mixed array). That is a lack of evidence, not a bug. Populate those fields in the sample to get precise types, and reach for the JSON viewer to confirm the shape of a deeply nested payload before you convert.
Deserializing with Jackson
Once you have the classes, binding is one call. Keep the root class public in its own file, then:
ObjectMapper mapper = new ObjectMapper();
Root order = mapper.readValue(json, Root.class);
A couple of options are worth knowing. mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) stops Jackson throwing when the JSON has keys your class does not declare, which is useful for third-party APIs that add fields over time. And if you prefer getters and setters or immutability, generate the fields here and layer Lombok (@Data) or records on top.
The gotchas that bite
- Missing annotations. A field whose name does not match the key stays null without
@JsonProperty. Generation gets this right; if you hand-edit, keep tags in sync. - Primitives swallow null. A
longfield turns a null or missing value into0. Use boxed types when the distinction matters, which is what the generator does. - One public class per file. Java allows only one public top-level class per file, so the generator marks the root public and the rest package-private. Split them into separate files if your project needs each one public.
- Large IDs as Double. If any value in the sample forces a numeric field to
Double, a large ID can lose precision. Have the API send big IDs as strings. - Unknown properties throw by default. Jackson fails on keys you did not model unless you disable
FAIL_ON_UNKNOWN_PROPERTIES. Decide which behavior you want.
Frequently asked questions
How do I convert JSON to a Java class?
Paste the JSON into the JSON to Java converter and it writes Jackson-ready POJOs, inferring nested classes, List types, Long/Double, and @JsonProperty tags. Then deserialize with ObjectMapper.readValue.
Why is my Java object empty after parsing JSON?
Almost always a field name that does not match the JSON key and no @JsonProperty tag, so Jackson cannot bind it. Generating the class gives every field the correct tag.
Should I use Long or long?
Use the boxed Long for JSON that may omit or null the field, because a primitive long cannot be null and will become 0 instead. The generator uses boxed types throughout for this reason.
How do I ignore extra JSON fields?
Set mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) or annotate the class with @JsonIgnoreProperties(ignoreUnknown = true), so new keys from an API do not break deserialization.
For the format underneath all this, see the guide on what JSON is, the same idea for Go in converting JSON to Go structs, and the roundup of free JSON tools for the rest of the toolkit.
Leave a Reply