Fix com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException When Deserializing JSON with Jackson

beginnerโ˜• Java2026-05-04| Java 8+, Jackson 2.x, Spring Boot 2.x/3.x, Maven/Gradle projects

Error Message

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "fieldName" (class com.example.MyDto), not marked as ignorable
#java#jackson#json#spring-boot#deserialization#objectmapper

The Scenario

You're calling a REST API or reading a JSON file. Jackson starts mapping the response into your DTO โ€” then blows up with:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "fieldName" (class com.example.MyDto), not marked as ignorable (4 known properties: ...)
  at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
  at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1001)

Sound familiar? The API shipped a new field โ€” say "createdAt" โ€” your DTO doesn't have it, and Jackson refuses to proceed. Or you renamed userName to displayName in your Java class but the JSON still sends the old key. Either way, same error.

Why Jackson Throws This

Jackson's ObjectMapper is strict by design. If the JSON contains a property with no matching field in the target class, it fails immediately rather than silently dropping the data. The intent is reasonable: catch schema mismatches early, before they cause subtle bugs downstream.

In practice, the error surfaces in a handful of predictable situations:

  • A third-party API adds new fields and you haven't updated your DTO yet
  • The JSON comes from an older version of the app with a different schema
  • You're sharing a DTO across services that have diverged over time
  • A field name has a typo somewhere in the chain

Quick Fix: Annotate the DTO Class

Slap @JsonIgnoreProperties(ignoreUnknown = true) on the class. Jackson will skip any JSON field it can't map โ€” no exception, no data loss on the fields you do have:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class MyDto {
    private String name;
    private int age;
    // getters and setters
}

This fix is surgical. Only MyDto becomes lenient โ€” everything else in your codebase stays strict. That's the right tradeoff when you trust your own internal DTOs but need to handle unpredictable responses from external APIs.

Global Fix: Configure ObjectMapper

Need lenient behavior everywhere? Configure the ObjectMapper once and use that instance throughout:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

// Use this mapper for all deserialization
MyDto dto = mapper.readValue(jsonString, MyDto.class);

The key point: configure it once, share the instance. Creating a new ObjectMapper per call is a common mistake โ€” it's expensive and easy to miss a config flag.

Spring Boot: Global ObjectMapper Config

Spring Boot manages its own ObjectMapper through auto-configuration โ€” you don't (and shouldn't) create one manually for controller deserialization. Add this to application.properties:

spring.jackson.deserialization.fail-on-unknown-properties=false

Or in application.yml:

spring:
  jackson:
    deserialization:
      fail-on-unknown-properties: false

Spring Boot picks this up automatically. It applies to the shared ObjectMapper used by all your controllers, RestTemplate calls, and WebClient responses.

If you've defined a custom ObjectMapper bean, apply the same flag there โ€” otherwise the property file setting won't affect your custom instance:

@Bean
public ObjectMapper objectMapper() {
    return new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}

When You Actually Want to Capture the Unknown Field

Ignoring unknown fields isn't always the right call. Sometimes that "unrecognized" field contains data you need.

Option 1: Add the field explicitly. If the JSON sends user_name but your Java field is userName, bridge the naming gap with @JsonProperty:

import com.fasterxml.jackson.annotation.JsonProperty;

public class MyDto {
    @JsonProperty("user_name")
    private String userName;
}

Option 2: Catch-all with a Map. When the schema is genuinely dynamic โ€” think webhook payloads or plugin APIs โ€” collect unmapped fields into a Map with @JsonAnySetter:

import com.fasterxml.jackson.annotation.JsonAnySetter;
import java.util.HashMap;
import java.util.Map;

public class MyDto {
    private String name;
    private Map<String, Object> extra = new HashMap<>();

    @JsonAnySetter
    public void setExtra(String key, Object value) {
        extra.put(key, value);
    }
}

Any field not declared on the class lands in extra. Nothing gets dropped.

Verification

Verify the fix with a focused unit test before calling it done:

@Test
void shouldDeserializeWithExtraFields() throws Exception {
    String json = "{\"name\": \"Alice\", \"age\": 30, \"unknownField\": \"ignored\"}";
    ObjectMapper mapper = new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    MyDto dto = mapper.readValue(json, MyDto.class);
    assertEquals("Alice", dto.getName());
    assertEquals(30, dto.getAge());
    // No exception โ€” fix confirmed
}

Still getting the exception after the fix? The most common culprit is a second ObjectMapper instance elsewhere in the call chain โ€” one that was created without the config flag. Search your codebase for new ObjectMapper() and audit each one.

Tips

Debugging deserialization failures is much easier when you can actually read the JSON. If the response is minified โ€” a wall of characters with no whitespace โ€” paste it into ToolCraft's JSON Formatter & Validator to expand it instantly. Spotting "user_name" vs "userName" in 800 bytes of minified JSON is painful; spotting it in a formatted tree takes two seconds.

Also worth thinking about: prefer the per-class annotation over the global config where you have a choice. @JsonIgnoreProperties(ignoreUnknown = true) on a specific DTO is explicit โ€” future readers know that class is intentionally lenient. Disabling the check globally is convenient but can hide real schema drift. Save the global flag for cases where you genuinely have no control over incoming JSON shape โ€” third-party APIs, legacy integrations, that sort of thing.

Related Error Notes