Here is a rough but more declarative solution. I haven't been able to get it down to a single annotation, but this seems to work well. Also not sure about performance on large data sets.

Given this JSON:

{
    "list": [
        {
            "wrapper": {
                "name": "Jack"
            }
        },
        {
            "wrapper": {
                "name": "Jane"
            }
        }
    ]
}

And these model objects:

public class RootObject {
    @JsonProperty("list")
    @JsonDeserialize(contentUsing = SkipWrapperObjectDeserializer.class)
    @SkipWrapperObject("wrapper")
    public InnerObject[] innerObjects;
}

and

public class InnerObject {
    @JsonProperty("name")
    public String name;
}

Where the Jackson voodoo is implemented like:

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface SkipWrapperObject {
    String value();
}

and

public class SkipWrapperObjectDeserializer extends JsonDeserializer<Object> implements
        ContextualDeserializer {
    private Class<?> wrappedType;
    private String wrapperKey;

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
            BeanProperty property) throws JsonMappingException {
        SkipWrapperObject skipWrapperObject = property
                .getAnnotation(SkipWrapperObject.class);
        wrapperKey = skipWrapperObject.value();
        JavaType collectionType = property.getType();
        JavaType collectedType = collectionType.containedType(0);
        wrappedType = collectedType.getRawClass();
        return this;
    }

    @Override
    public Object deserialize(JsonParser parser, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode objectNode = mapper.readTree(parser);
        JsonNode wrapped = objectNode.get(wrapperKey);
        Object mapped = mapIntoObject(wrapped);
        return mapped;
    }

    private Object mapIntoObject(JsonNode node) throws IOException,
            JsonProcessingException {
        JsonParser parser = node.traverse();
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(parser, wrappedType);
    }
}

Hope this is useful to someone!

Answer from Patrick on Stack Overflow
🌐
Baeldung
baeldung.com › home › json › jackson › mapping nested values with jackson
Mapping Nested Values with Jackson | Baeldung
January 8, 2024 - To map the nested brandName property, ... name property. We can instruct Jackson to unpack the nested property by using a combination of @JsonProperty and some custom logic that we add to our Product class:...
Top answer
1 of 4
37

Here is a rough but more declarative solution. I haven't been able to get it down to a single annotation, but this seems to work well. Also not sure about performance on large data sets.

Given this JSON:

{
    "list": [
        {
            "wrapper": {
                "name": "Jack"
            }
        },
        {
            "wrapper": {
                "name": "Jane"
            }
        }
    ]
}

And these model objects:

public class RootObject {
    @JsonProperty("list")
    @JsonDeserialize(contentUsing = SkipWrapperObjectDeserializer.class)
    @SkipWrapperObject("wrapper")
    public InnerObject[] innerObjects;
}

and

public class InnerObject {
    @JsonProperty("name")
    public String name;
}

Where the Jackson voodoo is implemented like:

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface SkipWrapperObject {
    String value();
}

and

public class SkipWrapperObjectDeserializer extends JsonDeserializer<Object> implements
        ContextualDeserializer {
    private Class<?> wrappedType;
    private String wrapperKey;

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
            BeanProperty property) throws JsonMappingException {
        SkipWrapperObject skipWrapperObject = property
                .getAnnotation(SkipWrapperObject.class);
        wrapperKey = skipWrapperObject.value();
        JavaType collectionType = property.getType();
        JavaType collectedType = collectionType.containedType(0);
        wrappedType = collectedType.getRawClass();
        return this;
    }

    @Override
    public Object deserialize(JsonParser parser, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode objectNode = mapper.readTree(parser);
        JsonNode wrapped = objectNode.get(wrapperKey);
        Object mapped = mapIntoObject(wrapped);
        return mapped;
    }

    private Object mapIntoObject(JsonNode node) throws IOException,
            JsonProcessingException {
        JsonParser parser = node.traverse();
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(parser, wrappedType);
    }
}

Hope this is useful to someone!

2 of 4
31

Your data is problematic in that you have inner wrapper objects in your array. Presumably your Vendor object is designed to handle id, name, company_id, but each of those multiple objects are also wrapped in an object with a single property vendor.

I'm assuming that you're using the Jackson Data Binding model.

If so then there are two things to consider:

The first is using a special Jackson config property. Jackson - since 1.9 I believe, this may not be available if you're using an old version of Jackson - provides UNWRAP_ROOT_VALUE. It's designed for cases where your results are wrapped in a top-level single-property object that you want to discard.

So, play around with:

objectMapper.configure(SerializationConfig.Feature.UNWRAP_ROOT_VALUE, true);

The second is using wrapper objects. Even after discarding the outer wrapper object you still have the problem of your Vendor objects being wrapped in a single-property object. Use a wrapper to get around this:

class VendorWrapper
{
    Vendor vendor;

    // gettors, settors for vendor if you need them
}

Similarly, instead of using UNWRAP_ROOT_VALUES, you could also define a wrapper class to handle the outer object. Assuming that you have correct Vendor, VendorWrapper object, you can define:

class VendorsWrapper
{
    List<VendorWrapper> vendors = new ArrayList<VendorWrapper>();

    // gettors, settors for vendors if you need them
}

// in your deserialization code:
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readValue(jsonInput, VendorsWrapper.class); 

The object tree for VendorsWrapper is analogous to your JSON:

VendorsWrapper:
    vendors:
    [
        VendorWrapper
            vendor: Vendor,
        VendorWrapper:
            vendor: Vendor,
        ...
    ]

Finally, you might use the Jackson Tree Model to parse this into JsonNodes, discarding the outer node, and for each JsonNode in the ArrayNode, calling:

mapper.readValue(node.get("vendor").getTextValue(), Vendor.class);

That might result in less code, but it seems no less clumsy than using two wrappers.

Discussions

java - How to let Jackson deserialize nested objects in custom deserializer - Stack Overflow
In my project I have some JsonDeserializers to deserialize abstract types in collections. Now I have a type which has a Collection property. How can I instruct Jackson to deserialize the nested More on stackoverflow.com
🌐 stackoverflow.com
java - Simple Jackson deserialization of nested objects - Stack Overflow
You have to create the POJO and then use the Jackson ObjectMapper API to read the JSON string to java object. More on stackoverflow.com
🌐 stackoverflow.com
java - Deserializing field from nested objects within JSON response with Jackson - Stack Overflow
All I really care about are the objects and next fields, but it's looking like I'll have to create a whole hierarchy of DTOs to successfully deserialize the nested fields. Is there a jackson annotation that would let me skip all of this? More on stackoverflow.com
🌐 stackoverflow.com
java - Jackson deserialize properties within nested JSON - Stack Overflow
I have a POJO that looks like this class Bean { private Instant created; private Instant updated; private String name; private int count; } and the input JSON data looks like this... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com › r/javahelp › conditionally deserialize nested json using jackson
r/javahelp on Reddit: Conditionally Deserialize Nested JSON using Jackson
April 11, 2021 -

I'm using Jackson to deserialize JSON that has a nested object with a different structure depending on the endpoint I'm calling. If I wanted to deserialize the outer JSON structure to a single class/object for both endpoints, how would I conditionally deserialize to one of two classes depending on the structure of the inner JSON?

API Endpoint 1
{
    "num_results": 20,
    "results": [
        {
        "title": "Florida man sentenced to 30 days in jail",
        "section": "Local"
        },
        // ...
    ]
}

API Endpoint 2
{
    "num_results": 20,
    "results": [
        {
        "section": "LOCAL",
        "name": "Local News"
        },
        // ...
    ]
}
Top answer
1 of 2
2
What about deserializing it to a pojo with these values: int numResults; Map results; If that won't work for both cases you will probably need 2 separate pojos that you deserialize to, and then just use the correct type for deserialization on each endpoint.
2 of 2
1
Please ensure that: Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions You include any and all error messages in full You ask clear questions You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions. Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar If any of the above points is not met, your post can and will be removed without further warning. Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis ) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit. Code blocks look like this: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above. If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures. To potential helpers Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice. I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
🌐
Syntax Savvy
learn.syntaxsavvy.dev › langs › tools › jackson › advanced_jackson_usage › using_jackson_with_nested_objects
Using Jackson with nested objects | Syntax Savvy
To serialize and deserialize nested objects with Jackson, we follow the same basic steps as we do for non-nested objects. We create a ObjectMapper instance and use its methods to serialize and deserialize the object.
🌐
Medium
medium.com › swlh › fasterxml-jackson-tips-for-json-in-java-3a910e846115
FasterXML/jackson Tips for JSON in Java | by Kamer Elciyar | The Startup | Medium
March 14, 2020 - Q2: How to use different field names in POJO to map JSON? Q3: How to deserialize nested JSON objects? Q4: How to create a custom deserializer? Q5: How to deserialize enum values? ... This article is not a zero-to-hero-like article. So, I will not start from basics but introduce Jackson with a ...
🌐
Stack Overflow
stackoverflow.com › questions › 25379510 › how-to-let-jackson-deserialize-nested-objects-in-custom-deserializer
java - How to let Jackson deserialize nested objects in custom deserializer - Stack Overflow
wiki.fasterxml.com/JacksonPolymorphicDeserialization . It may eliminate the need to custom deserializers. ... No I haven't. I will take a look at it when I get the time. Thank you for the link. ... In this case (ok it is old but for someone it could be an help) you actually have a nested recursive object, so you can simply extract the code to deserialize a person on a Node and iterate over his friendNodes invoking the same function
🌐
Salty Egg
hzhou.me › home › 编程人生 › java › jackson: deserialize nested object
Jackson: deserialize nested object | Salty Egg
March 29, 2026 - The when I tried to deserialize {"animals":[{"name":"1"},{"name":"2"}]} into Zoo instance, it will will have such error as below: The error message is very clear. (Note: For Jackson version 1.x, you may have other error, as find object as LinkedHashMap, cannot cast to SomeClass.)
Top answer
1 of 1
7

You have to create the POJO and then use the Jackson ObjectMapper API to read the JSON string to java object.

Here is the working code basing on your sample string.

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({ "info", "data" })
public class Process {

    @JsonProperty("info")
    private String info;
    @JsonProperty("data")
    private Data data;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("info")
    public String getInfo() {
        return info;
    }

    @JsonProperty("info")
    public void setInfo(String info) {
        this.info = info;
    }

    @JsonProperty("data")
    public Data getData() {
        return data;
    }

    @JsonProperty("data")
    public void setData(Data data) {
        this.data = data;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({ "id", "cars" })
public class Data {

    @JsonProperty("id")
    private String id;
    @JsonProperty("cars")
    private List<Car> cars = null;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("id")
    public String getId() {
        return id;
    }

    @JsonProperty("id")
    public void setId(String id) {
        this.id = id;
    }

    @JsonProperty("cars")
    public List<Car> getCars() {
        return cars;
    }

    @JsonProperty("cars")
    public void setCars(List<Car> cars) {
        this.cars = cars;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}


@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({ "id" })
public class Car {

    @JsonProperty("id")
    private String id;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("id")
    public String getId() {
        return id;
    }

    @JsonProperty("id")
    public void setId(String id) {
        this.id = id;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

Code to deserialize the JSON string.

import java.io.IOException;
import java.util.List;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MainApp {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        String input = "{\r\n" + 
                "  \"info\": \"processing\",\r\n" + 
                "  \"data\": {\r\n" + 
                "    \"id\": \"123\",\r\n" + 
                "    \"cars\": [\r\n" + 
                "      {\r\n" + 
                "        \"id\": \"1\"\r\n" + 
                "      },\r\n" + 
                "      {\r\n" + 
                "        \"id\": \"2\"\r\n" + 
                "      }\r\n" + 
                "    ]\r\n" + 
                "  }\r\n" + 
                "}";
        ObjectMapper mapper = new ObjectMapper();
        Process process = mapper.readValue(input, Process.class);
        System.out.println(process.getInfo());
        Data data = process.getData();
        List<Car> cars = data.getCars();
        for(Car car : cars) {
            System.out.println(car.getId());
        }

    }

}

Hope this helps.

Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 78501074 › jackson-deserialize-properties-within-nested-json
java - Jackson deserialize properties within nested JSON - Stack Overflow
Sorry to disappoint but as it seems it is an open issue in Jackson: https://github.com/FasterXML/jackson-annotations/issues/42 If you want you can upvote this issue and they might add it in the future, but for now you need to do it manually with a custom deserializer.
🌐
GitHub
github.com › FasterXML › jackson-module-kotlin › issues › 411
Problems with deserializing nested object with Kotlin + Jackson Module · Issue #411 · FasterXML/jackson-module-kotlin
January 27, 2021 - jacksonModuleKotlinVersion=2.12.1 implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jacksonModuleKotlinVersion}") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:${jacksonModuleKotlinVersion}") implementation("com.fasterxml.jackson.core:jackson-annotations:${jacksonModuleKotlinVersion}") It seems that the nested data object parsed like LinkedHashMap, not as UserResponse object.
Author: FasterXML
🌐
GitHub
github.com › FasterXML › jackson-databind › issues › 3000
Attributes and nested de-serialization · Issue #3000 · FasterXML/jackson-databind
December 23, 2020 - @JsonDeserialize(using = Foo.Deserializer.class) public static class Foo { Bar bar; String message; public static class Deserializer extends StdDeserializer<Foo> { public Deserializer() { super(Foo.class); } @Override public Foo deserialize(JsonParser p, DeserializationContext ctx) throws IOException { Foo foo = new Foo(); foo.message = (String)ctx.getAttribute("message"); JsonNode node = p.getCodec().readTree(p); JsonNode bar = node.get("bar"); if (bar != null) { foo.bar = p.getCodec().treeToValue(bar, Bar.class); } return foo; } } } @JsonDeserialize(using = Bar.Deserializer.class) public sta
Author: FasterXML
🌐
CodingTechRoom
codingtechroom.com › question › deserialize-nested-json-jackson
How to Deserialize Nested JSON Objects Using Jackson - CodingTechRoom
Solution: Ensure you create separate classes for each nested object, such as 'Address' in this case. Mistake: Forgetting to annotate fields with @JsonProperty when they differ from Java field names. Solution: Use @JsonProperty to match JSON field names with Java attributes if they don’t match. Mistake: Incorrectly handling JSON arrays within nested objects.
🌐
Google Groups
groups.google.com › g › jackson-user › c › MULinpe4bmk
Deserializing nested JSON to Java object
{ "personal": { "name": "John Doe", ... how do I deserializing the json object in both scenarios? ... Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message ... That's a complex example. You're trying to take the property name of a parent object and make it a property value of a child object. This is possible with Jackson but is a more ...
Top answer
1 of 1
18

I see at least two approaches to do this if you want to get rid of wrapper classes. The first is to use the Jackson Tree Model (JsonNode) and the second is to use a deserialization feature called UNWRAP_ROOT_VALUE.


Alternative 1: Use JsonNode

When deserializing JSON using Jackson there are multiple ways to control what type of objects that are to be created. The ObjectMapper can deserialize the JSON to e.g. a Map, JsonNode (via the readTree-method) or a POJO.

If you combine the readTree-method with the POJO conversion the wrappers can be completely removed. Example:

// The author class (a bit cleaned up)
public class Author {
    private final String givenName;
    private final String surname;

    @JsonCreator
    public Author(
            @JsonProperty("given-name") final String givenName,
            @JsonProperty("surname") final String surname) {

        this.givenName = givenName;
        this.surname = surname;
    }

    public String getGivenName() {
        return givenName;
    }

    public String getSurname() {
        return surname;
    }
}

The deserialization can then look something like this:

// The JSON
final String json = "{\"authors\":{\"author\":[{\"given-name\":\"AdrienneH.\",\"surname\":\"Kovacs\"},{\"given-name\":\"Philip\",\"surname\":\"Moons\"}]}}";

ObjectMapper mapper = new ObjectMapper();

// Read the response as a tree model
final JsonNode response = mapper.readTree(json).path("authors").path("author");

// Create the collection type (since it is a collection of Authors)
final CollectionType collectionType =
        TypeFactory
                .defaultInstance()
                .constructCollectionType(List.class, Author.class);

// Convert the tree model to the collection (of Author-objects)
List<Author> authors = mapper.reader(collectionType).readValue(response);

// Now the authors-list is ready to use...

If you use this Tree Model-approach the wrapper classes can be completely removed.


Alternative 2: remove one of the wrappers and unwrap the root value The second approach is to remove only one of the wrappers. Assume that you remove the Authors class but keep the Response-wrapper. If you add the a @JsonRootName-annotation you can later unwrap the top-level name.

@JsonRootName("authors") // This is new compared to your example
public class Response {
    private final List<Author> authors;

    @JsonCreator
    public Response(@JsonProperty("author") final List<Author> authors) {
        this.authors = authors;
    }

    @JsonProperty("author")
    public List<Author> getAuthors() {
        return authors;
    }
}

Then, for your mapper simply use:

ObjectMapper mapper = new ObjectMapper();

// Unwrap the root value i.e. the "authors"
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
final Response responsePojo = mapper.readValue(json, Response.class);

The second approach only removes one of the wrapper classes but instead the parsing function is quite pretty.

🌐
Stack Overflow
stackoverflow.com › questions › 56418361 › deserialize-json-with-list-of-nested-objects › 56422254
java - Deserialize json with list of nested objects - Stack Overflow
Assuming Class1 has fields prop1 and prop2, and NestedProp has fields p1 and p2, what class has field nestedProp? ... You have two arrays in your JSON payloads. So, you need to create extra POJO for it. See below example: import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.util.List; public class JsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); ObjectMapper mapper = new ObjectMapper(); Root root = mapper.readValue(jsonFile, Root.class); System.out.println(root); } } class Roo
🌐
QA Automation Expert
qaautomation.expert › 2021 › 11 › 08 › how-to-create-nested-json-object-using-jackson-api
How to create Nested JSON Object using POJO – Jackson API
August 20, 2024 - Here, I have used ObjectMapper for reading and writing JSON, either to and from basic POJOs (Plain Old Java Objects), or to and from a general-purpose JSON Tree Model (JsonNode), as well as related functionality for performing conversions. We can save this JSON payload in a file in the project or any location of your choice. Here, I’m saving this Nested JSON Payload in a file within src/test/resources.
🌐
Makeseleniumeasy
makeseleniumeasy.com › 2020 › 09 › 05 › rest-assured-tutorial-45-fetch-value-from-nested-json-object-using-jsonnode-jackson-at-method
REST Assured Tutorial 45 – Fetch Value From Nested JSON Object Using JsonNode – Jackson – at() Method
September 5, 2020 - We need to use class ObjectMapper provided by Jackson API. ObjectMapper class provides a method “readTree()” which is responsible to deserialize JSON content as tree expressed using a set of JsonNode instances.
🌐
Learn IT University
learn-it-university.com › home › easily deserialize nested json objects in jackson
Easily Deserialize Nested JSON Objects in Jackson - Learn IT University
June 23, 2024 - One approach to simplifying the deserialization of nested JSON objects in Jackson involves leveraging the UNWRAP_ROOT_VALUE feature.