jshree
jshree

Reputation: 10441

Jackson with JSON: Unrecognized field, not marked as ignorable

I need to convert a certain JSON string to a Java object. I am using Jackson for JSON handling. I have no control over the input JSON (I read from a web service). This is my input JSON:

{"wrapper":[{"id":"13","name":"Fred"}]}

Here is a simplified use case:

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 entity class is:

public Class Student { 
    private String name;
    private String id;
    //getters & setters for name & id here
}

My Wrapper class is basically a container object to get my list of students:

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

I keep getting this error and "wrapper" returns null. I am not sure what's missing. Can someone help please?

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
    Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
 at [Source: java.io.StringReader@1198891; line: 1, column: 13] 
    (through reference chain: Wrapper["wrapper"])
 at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
    .from(UnrecognizedPropertyException.java:53)

Upvotes: 1036

Views: 1483683

Answers (30)

Jim Ferrans
Jim Ferrans

Reputation: 31012

Jackson is complaining because it can't find a field in your class Wrapper that's called wrapper. It's doing this because your JSON object has a property called wrapper.

I think the fix is to rename your Wrapper class's students field to wrapper.

Upvotes: 20

Satyajit Bhatt
Satyajit Bhatt

Reputation: 261

Simple and smart solution is whenever get any unrecognized field then always go to that POJO class which you are using in response. First check that response like in your example there is JSON :

{"wrapper":[{"id":"13","name":"Fred"}]}

Just simply bind class in response called Wrapper which contains id as String and name as string and bind that class. You will never get those exception.

Simply it means you are not using those attributes or fields which is coming from response... That's it!!

Upvotes: 0

Steven Chou
Steven Chou

Reputation: 2215

In my case I got a similar error that I couldn't deserialize JSON to map a Java field which is using Optional<>. I ended up solving it by registering Jdk8Module;

ObjectMapper MAPPER = new ObjectMapper()
                          .registerModule(new Jdk8Module());

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
    <version>${jackson.version}</version>
</dependency>

Upvotes: 0

vhs
vhs

Reputation: 10089

Sounds like a job for @Jacksonized using a gradle as an example add jackson databind:

implementation("com.fasterxml.jackson.core:jackson-databind:2.17.2")

Then Annotate your Wrapper class using the annotation like:

@Data
@Jacksonized
public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

And you should then be able to use ObjectMapper and JsonMapper without hacks.

Upvotes: 1

Scott
Scott

Reputation: 1856

using Jackson 2.6.0, this worked for me:

private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

or with the setting:

@JsonIgnoreProperties(ignoreUnknown = true)

Upvotes: 159

Oleksandr Yefymov
Oleksandr Yefymov

Reputation: 6509

Simple solution for Java 11 and newer:

var mapper = new ObjectMapper()
        .registerModule(new JavaTimeModule())
        .disable(FAIL_ON_UNKNOWN_PROPERTIES)
        .disable(WRITE_DATES_AS_TIMESTAMPS)
        .enable(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

Important for ignoring is disabling 'FAIL_ON_UNKNOWN_PROPERTIES'

Upvotes: 13

Akash Verma
Akash Verma

Reputation: 847

Below is what I tried to suppress the unknown props which did not want to parse. Sharing Kotlin code

val myResponse = jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .readValue(serverResponse, FooResponse::class.java)

Upvotes: -1

Omkar Patkar
Omkar Patkar

Reputation: 137

I faced similar issue, only difference is i was working with YAML file instead of JSON file. So i was using YamlFactory() when creating an ObjectMapper. Also, the properties of my Java POJO were priviate. However, the solution mentioned in all these answers did not help. I mean, it stopped throwing error and started returning Java object but the properties of the java object would be null.

I just did the following: -

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

And without the need of: -

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Now, i am able to deserialize data from Yaml file into Java object. All properties are not null now. This solution should work for JSON approach also.

Upvotes: 4

xilef
xilef

Reputation: 2397

I ran into this once when my JSON payload included a property that was not recognised by the API. The solution was to rename/remove the offending property.

Upvotes: 0

Rog&#233;rio Viana
Rog&#233;rio Viana

Reputation: 170

ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);

Upvotes: -1

Mopto
Mopto

Reputation: 390

Json field:

 "blog_host_url": "some.site.com"

Kotlin field

var blogHostUrl: String = "https://google.com"

In my case i needed just to use @JsonProperty annotation in my dataClass.

Example:

data class DataBlogModel(
       @JsonProperty("blog_host_url") var blogHostUrl: String = "https://google.com"
    )

Here's article: https://www.baeldung.com/jackson-name-of-property

Upvotes: 0

mytwocentsads
mytwocentsads

Reputation: 201

I have tried the below method and it works for such JSON format reading with Jackson. Use the already suggested solution of: annotating getter with @JsonProperty("wrapper")

Your wrapper class

public Class Wrapper{ 
  private List<Student> students;
  //getters & setters here 
} 

My Suggestion of wrapper class

public Class Wrapper{ 

  private StudentHelper students; 

  //getters & setters here 
  // Annotate getter
  @JsonProperty("wrapper")
  StudentHelper getStudents() {
    return students;
  }  
} 


public class StudentHelper {

  @JsonProperty("Student")
  public List<Student> students; 

  //CTOR, getters and setters
  //NOTE: If students is private annotate getter with the annotation @JsonProperty("Student")
}

This would however give you the output of the format:

{"wrapper":{"student":[{"id":13,"name":Fred}]}}

Also for more information refer to https://github.com/FasterXML/jackson-annotations

Upvotes: 20

superuserdo
superuserdo

Reputation: 1657

I fixed this problem by simply changing the signatures of my setter and getter methods of my POJO class. All I had to do was change the getObject method to match what the mapper was looking for. In my case I had a getImageUrl originally, but the JSON data had image_url which was throwing the mapper off. I changed both my setter and getters to getImage_url and setImage_url.

Upvotes: 7

Rohitesh
Rohitesh

Reputation: 987

What worked for me, was to make the property public.

Upvotes: 7

Suraj
Suraj

Reputation: 3137

If you want to apply @JsonIgnoreProperties to all class in you application then the best way it is override Spring boot default jackson object.

In you application config file define a bean to create jackson object mapper like this.

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

Now, you don't need to mark every class and it will ignore all unknown properties.

Upvotes: 16

TedTrippin
TedTrippin

Reputation: 3662

Problem is your property in your JSON is called "wrapper" and your property in Wrapper.class is called "students".

So either...

  1. Correct the name of the property in either the class or JSON.
  2. Annotate your property variable as per StaxMan's comment.
  3. Annotate the setter (if you have one)

Upvotes: 12

Praj
Praj

Reputation: 714

As per this documentation, you can use the Jackson2ObjectMapperBuilder to build your ObjectMapper:

@Autowired
Jackson2ObjectMapperBuilder objectBuilder;

ObjectMapper mapper = objectBuilder.build();
String json = "{\"id\": 1001}";

By default, Jackson2ObjectMapperBuilder disables the error unrecognizedpropertyexception.

Upvotes: 0

heringer
heringer

Reputation: 3208

Just in case anyone else is using force-rest-api like me, here is how I used this discussion to solve it (Kotlin):

var result = forceApi.getSObject("Account", "idhere")
result.jsonMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,  false)
val account: Account = result.`as`(Account::class.java)

It looks like force-rest-api is using an old version of jackson's.

Upvotes: 1

matias.g.rodriguez
matias.g.rodriguez

Reputation: 849

If for some reason you cannot add the @JsonIgnoreProperties annotations to your class and you are inside a web server/container such as Jetty. You can create and customize the ObjectMapper inside a custom provider

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

@Provider
public class CustomObjectMapperProvider implements ContextResolver<ObjectMapper> {

    private ObjectMapper objectMapper;

    @Override
    public ObjectMapper getContext(final Class<?> cls) {
        return getObjectMapper();
    }

    private synchronized ObjectMapper getObjectMapper() {
        if(objectMapper == null) {
            objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
        return objectMapper;
    }
}

Upvotes: 5

Somehow after 45 posts and 10 years, no one has posted the correct answer for my case.

@Data //Lombok
public class MyClass {
    private int foo;
    private int bar;

    @JsonIgnore
    public int getFoobar() {
      return foo + bar;
    }
}

In my case, we have a method called getFoobar(), but no foobar property (because it's computed from other properties). @JsonIgnoreProperties on the class does not work.

The solution is to annotate the method with @JsonIgnore

Upvotes: 10

antken
antken

Reputation: 989

The shortest solution without setter/getter is to add @JsonProperty to a class field:

public class Wrapper {
    @JsonProperty
    private List<Student> wrapper;
}

public class Student {
    @JsonProperty
    private String name;
    @JsonProperty
    private String id;
}

Also, you called students list "wrapper" in your json, so Jackson expects a class with a field called "wrapper".

Upvotes: 1

ddc
ddc

Reputation: 965

Adding setters and getters solved the problem, what I felt is the actual issue was how to solve it but not how to suppress/ignore the error. I got the error "Unrecognized field.. not marked as ignorable.."

Though I use the below annotation on top of the class it was not able to parse the json object and give me the input

@JsonIgnoreProperties(ignoreUnknown = true)

Then I realized that I did not add setters and getters, after adding setters and getters to the "Wrapper" and to the "Student" it worked like a charm.

Upvotes: 73

Danail Tsvetanov
Danail Tsvetanov

Reputation: 613

FAIL_ON_UNKNOWN_PROPERTIES option is true by default:

FAIL_ON_UNKNOWN_PROPERTIES (default: true)
Used to control whether encountering of unknown properties (one for which there is no setter; and there is no fallback "any setter" method defined using @JsonAnySetter annotation) should result in a JsonMappingException (when enabled), or just quietly ignored (when disabled)

Upvotes: 4

van17
van17

Reputation: 171

When we are generating getters and setters, specially which starts with 'is' keyword, IDE generally removes the 'is'. e.g.

private boolean isActive;

public void setActive(boolean active) {
   isActive = active;
}

public isActive(){
   return isActive;
}

In my case, i just changed the getter and setter.

private boolean isActive;

public void setIsActive(boolean active) {
   isActive = active;
}

public getIsActive(){
   return isActive;
}

And it was able to recognize the field.

Upvotes: 3

user9999
user9999

Reputation: 154

In my case a I have to add public getters and setters to leave fields private.

ObjectMapper mapper = new ObjectMapper();
Application application = mapper.readValue(input, Application.class);

I use jackson-databind 2.10.0.pr3 .

Upvotes: 1

Gank
Gank

Reputation: 4667

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties

Upvotes: 1

cwa
cwa

Reputation: 156

This may not be the same problem that the OP had but in case someone got here with the same mistake I had then this will help them solve their problem. I got the same error as the OP when I used an ObjectMapper from a different dependency as the JsonProperty annotation.

This works:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;

Does NOT work:

import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8
import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3

Upvotes: 7

Manish Kumar
Manish Kumar

Reputation: 7189

One other possibility is this property in the application.properties spring.jackson.deserialization.fail-on-unknown-properties=false, which won't need any other code change in your application. And when you believe the contract is stable, you can remove this property or mark it true.

Upvotes: 7

Ariel Kogan
Ariel Kogan

Reputation: 14577

You can use Jackson's class-level annotation:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

It will ignore every property you haven't defined in your POJO. Very useful when you are just looking for a couple of properties in the JSON and don't want to write the whole mapping. More info at Jackson's website. If you want to ignore any non declared property, you should write:

@JsonIgnoreProperties(ignoreUnknown = true)

Upvotes: 1430

neverwinter
neverwinter

Reputation: 810

set public your class fields not private.

public Class Student { 
    public String name;
    public String id;
    //getters & setters for name & id here
}

Upvotes: 5

Related Questions