Question
I need to convert a JSON string into a Java object using Jackson. The JSON comes from a web service, so I cannot change its structure.
This is the JSON input:
{"wrapper":[{"id":"13","name":"Fred"}]}
Here is a simplified version of my code:
private void tryReading() {
String jsonStr = "{\"wrapper\":[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = null;
try {
wrapper = mapper.readValue(jsonStr, Wrapper.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wrapper = " + wrapper);
}
My Student class is:
public class Student {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
My Wrapper class is intended to contain the list of students:
public class Wrapper {
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
However, Jackson throws this exception:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException:
Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
Why does this happen, and how should I structure my Java classes or annotations so Jackson can map this JSON correctly?
Short Answer
By the end of this page, you will understand why Jackson throws an UnrecognizedPropertyException, how JSON field names must match Java properties, and how to fix mismatches using proper class design or @JsonProperty. You will also learn common patterns for mapping nested JSON objects in Java.
Concept
Jackson converts JSON into Java objects by matching JSON property names to Java fields or setter/getter names.
In the JSON:
{
"wrapper": [
{"id": "13", "name": "Fred"}
]
}
The top-level object has one property named wrapper.
But your Java class looks like this:
public class Wrapper {
private List<Student> students;
}
Jackson tries to map the JSON property wrapper to a Java property named wrapper, but your class only has a property named students. Since there is no matching field, Jackson raises:
Unrecognized field "wrapper"
This matters because JSON-to-object mapping depends on structure and naming. If the JSON shape and Java class shape do not match, deserialization fails.
Mental Model
Think of Jackson like a mail sorter reading labels on boxes.
- JSON keys are the labels on the boxes.
- Java fields are the slots where those boxes should go.
If the sorter sees a box labeled wrapper, it looks for a slot named wrapper.
If your class only has a slot named students, the sorter does not know where to put the wrapper box, so it throws an error.
You can fix this in two ways:
- Rename the slot to
wrapper - Add a note saying: "When you see
wrapper, put it instudents" using@JsonProperty("wrapper")
Jackson is strict by default because it assumes unexpected fields may indicate a bug.
Syntax and Examples
Jackson maps JSON properties to Java properties using field names, setters, getters, or annotations.
Option 1: Match the JSON field name directly
import java.util.List;
public class Wrapper {
private List<Student> wrapper;
public List<Student> getWrapper() {
return wrapper;
}
public void setWrapper(List<Student> wrapper) {
this.wrapper = wrapper;
}
}
This works because the JSON contains:
{"wrapper":[...]}
So Jackson finds a matching Java property named wrapper.
Option 2: Keep your preferred Java name with @JsonProperty
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Wrapper {
List<Student> students;
List<Student> {
students;
}
{
.students = students;
}
}
Step by Step Execution
Consider this code:
String jsonStr = "{\"wrapper\":[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
Wrapper result = mapper.readValue(jsonStr, Wrapper.class);
And this class:
public class Wrapper {
@JsonProperty("wrapper")
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
What happens step by step
- Jackson reads the JSON string.
- It sees a top-level JSON object.
- Inside that object, it finds a property named
wrapper. - It looks at the
Wrapperclass for a matching property. - Because of
@JsonProperty("wrapper"), Jackson knows that JSON maps to Java .
Real World Use Cases
This kind of mapping is common whenever Java applications consume external JSON.
Common real-world scenarios
- Calling REST APIs where the response wraps data inside keys like
data,results,items, orwrapper - Reading third-party web service responses that use names you cannot control
- Importing data feeds from vendors or partners
- Parsing configuration files where JSON keys do not match your preferred Java naming
- Backend services that deserialize request bodies into domain objects
Example API response patterns
{"data":[{"id":1,"name":"Alice"}]}
{"results":[{"id":
Real Codebase Usage
In real projects, developers usually combine matching models, annotations, and defensive configuration.
Common patterns
1. Use DTOs that mirror external JSON
When consuming an API, it is common to create a DTO class specifically for the API response.
public class StudentResponse {
@JsonProperty("wrapper")
private List<Student> students;
}
This keeps external API structure separate from internal business models.
2. Use @JsonProperty for naming mismatches
This is the most direct and readable fix when the JSON name and Java name differ.
@JsonProperty("wrapper")
private List<Student> students;
3. Ignore unknown fields when APIs evolve
Some APIs add extra fields over time. To avoid breaking your code, developers often ignore fields they do not use.
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Wrapper {
@JsonProperty("wrapper")
private List<Student> students;
}
This does not fix a wrong field mapping, but it helps when the JSON contains extra properties.
Common Mistakes
1. Java field name does not match JSON field name
Broken example:
public class Wrapper {
private List<Student> students;
}
JSON:
{"wrapper":[{"id":"13","name":"Fred"}]}
Problem:
- JSON has
wrapper - Java has
students - Jackson cannot match them automatically
Fix:
@JsonProperty("wrapper")
private List<Student> students;
2. Modeling the JSON structure incorrectly
Broken idea:
Trying to deserialize the JSON directly into List<Student>
Comparisons
| Approach | When to use it | Example | Pros | Cons |
|---|---|---|---|---|
| Rename Java field to match JSON | When you are fine using the API's field name in Java | private List<Student> wrapper; | Simple, no annotation needed | Java code may be less expressive |
Use @JsonProperty | When you want a cleaner Java name | @JsonProperty("wrapper") private List<Student> students; | Clear mapping, readable Java code | Requires annotation |
| Ignore unknown fields | When the JSON has extra fields you do not care about | @JsonIgnoreProperties(ignoreUnknown = true) | Makes code more tolerant | Does not solve wrong field-name mapping |
| Parse into manually |
Cheat Sheet
Quick fix
If your JSON is:
{"wrapper":[{"id":"13","name":"Fred"}]}
and your Java field is named students, use:
@JsonProperty("wrapper")
private List<Student> students;
Core rule
Jackson maps JSON keys to Java properties by name.
- JSON key
wrapper-> Java propertywrapper - or JSON key
wrapper-> Java propertystudentswith@JsonProperty("wrapper")
Minimal working classes
public class {
String id;
String name;
String { id; }
{ .id = id; }
String { name; }
{ .name = name; }
}
FAQ
Why does Jackson say Unrecognized field "wrapper"?
Because the JSON contains a property named wrapper, but your Java class does not have a matching property with that name.
How do I map a JSON field to a differently named Java field?
Use @JsonProperty:
@JsonProperty("wrapper")
private List<Student> students;
Can I just rename the Java field instead of using an annotation?
Yes. If you rename students to wrapper, Jackson can map it automatically.
Why can’t I deserialize this directly into List<Student>?
Because the top-level JSON is an object, not an array. The array is inside the wrapper property.
Does @JsonIgnoreProperties(ignoreUnknown = true) fix this problem?
No. It only ignores extra fields. It does not map wrapper to students.
Do I need getters and setters for Jackson?
Usually yes, unless you configure Jackson to use fields directly or use supported constructors/records.
Mini Project
Description
Build a small Java program that reads a JSON API response containing a wrapped list of students and converts it into Java objects using Jackson. This project demonstrates how to model top-level wrapper objects correctly and how to use @JsonProperty when the JSON field name does not match your preferred Java field name.
Goal
Create a working Java program that deserializes a wrapped JSON response into a Wrapper object and prints each student's ID and name.
Requirements
Create a Student class with id and name properties.
Create a wrapper class that maps the JSON field wrapper to a Java List<Student>.
Deserialize the JSON string using ObjectMapper.
Print all students from the parsed result.
Handle deserialization errors safely.
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.