34

i got a deserialization problem:

This is my class:

public class Response {

    private Object ResObj;
    private int ResInt;

    public Object getResObj() {
        return ResObj;
    }

    public int getResInt() {
        return ResInt;
    } 
} 

the JSON i want to deserialize is:

{"ResObj":{"ClientNum":"12345","ServerNum":"78945","IdNum":"020252"},"ResInt":0}

I get this exception:

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ResObj" , not marked as ignorable (0 known properties: ])
 at [Source: java.io.StringReader@1f758500; line: 1, column: 20] (through reference chain: ["ResObj"])

I don't want to add:

@JsonIgnoreProperties(ignoreUnknown = true)

because I want to get the ResObj...

if I add the annotation, it pass but it will set it as null .. which I don't want.

Rizvi
  • 287
  • 3
  • 14
user2212726
  • 1,225
  • 3
  • 16
  • 23

7 Answers7

90

If you don't want to have a setter in your bean and only use fields and getters, you can use the visibility checker of ObjectMapper to allow field visibility.
Something like following:

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setVisibility(VisibilityChecker.Std.defaultInstance().withFieldVisibility(JsonAutoDetect.Visibility.ANY));
improbable
  • 2,308
  • 2
  • 15
  • 28
Jay
  • 1,539
  • 1
  • 16
  • 27
  • If this resolves the issue, @user2212726 can you please approve so it can be useful to others as well? – Jay Aug 26 '15 at 14:24
  • You should give the complete conf. How do you make this "mapper" object you've created yourself to be used by Spring ? – Tristan Apr 07 '20 at 12:23
  • @Tristan just wrap the above piece of code in a method and annotate it with `@Bean` if you want example, check this - https://stackoverflow.com/a/32842962/471467 – Jay Apr 08 '20 at 12:35
  • Well, this may fail as you can read below the answer you are quoting. – Tristan Apr 08 '20 at 13:06
  • By "may fail" if you are referring to spring boot then there is a comment which says that use a different name. Makes sense? – Jay Apr 08 '20 at 13:38
  • Visibility checker is deprecated, having only `mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);` without required fields doesn't resolve for me the exception. Update your answer. – improbable Dec 22 '20 at 11:11
  • @improbable answer is from 2014 and in the context of the question asked at that time. But as you rightly mentioned, `setVisibilityChecker` is deprecated, did you try to use `setVisibility(VisibilityChecker)` as mentioned in javadoc? – Jay Dec 24 '20 at 00:00
  • @Jay `setVisibility(VisibilityChecker)` should be used for this purpose instead. Read Javadocs: `/** * @deprecated Since 2.6 use {@link #setVisibility(VisibilityChecker)} instead. */ @Deprecated` – improbable Dec 24 '20 at 12:04
12

You need Setter methods to allow Jackson to set the properties, and you need to change the fields in the json to begin with a lower case letter:

public class Response {

    private Object ResObj;
    private int ResInt;

    public Object getResObj() {
        return ResObj;
    }

    public void setResObj(Object ResObj) {
        this.ResObj = ResObj;
    }

    // ...
}

and:

{"resObj":{"clientNum":"12345","serverNum":"78945","idNum":"020252"},"resInt":0}

The reason for the JSON change is that the Jackson bean serialisation will reflect over the class, and when it sees getXyz() and setXyz() methods it will map these to a Json field named "xyz" (and not "Xyz").

I think there are several ways to override this behaviour, one is to use the one of the Jackson annotations.

jon hanson
  • 8,722
  • 2
  • 37
  • 61
  • apparently you do not need setters – user2212726 May 05 '14 at 10:15
  • Depends how you've configured your de/serializer. I think by default Jackson will try bean-style serialisation - based on the getXXX methods available on your classes. Have you tried adding the set method? – jon hanson May 05 '14 at 10:26
  • yea sure.. it didn't effect .. still the same error – user2212726 May 05 '14 at 10:36
  • You need to change the JSON fields to begin with a lower case field as well. – jon hanson May 06 '14 at 17:53
  • Where is this documented jon? I'm trying to unmarshal some JSON and I'm finding a very hard time finding good documentation for the XML DSL, which is what we're using. This would explain my issue, but I don't control the JSON I'm receiving :( – Ungeheuer Apr 08 '20 at 22:37
  • 1
    @Ungeheuer Don't know to be honest - most docs seem to be on 3rd party sites. Most of my knowledge of Jackson came from having to debug the implementation code every time it did something weird. I've since stopped using it as it's just too idiosyncratic - you invariably have to use annotations everywhere to try and get it to cooperate. – jon hanson Apr 14 '20 at 08:37
6

I think you should try this

public class Response {
    @JsonProperty
    private Object ResObj;
    @JsonProperty
    private int ResInt;

    public Object getResObj() {
        return ResObj;
    }

    public int getResInt() {
        return ResInt;
    } 
} 

It will resolve your issue with UnrecognizedPropertyExceptions

Ashish
  • 1,309
  • 1
  • 11
  • 17
0
public class Response {
    public Object ResObj;
    public int ResInt;

    public Object getResObj() {
        return ResObj;
    }

    public int getResInt() {
        return ResInt;
    } 
} 

Use this to resolve the above issue.

Arsen Davtyan
  • 1,891
  • 8
  • 23
  • 40
0

I have sorted this problem using the Jackson library. Here is my code snippet.

**Main Class with JSON String in all lower case:**

 public class MainClass {

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

    String jsonStr = "{\r\n" + "    \"resObj\": {\r\n" + "      \"clientNum\": 
               \"12345\",\r\n"
            + "     \"serverNum\": \"78945\",\r\n" + "      \"idNum\": 
          \"020252\"\r\n" + "   },\r\n"
            + " \"resInt\": 0\r\n" + "}";

    ObjectMapper mapper = new ObjectMapper();

    MyPojo details = mapper.readValue(jsonStr, MyPojo.class);

    System.out.println("value of clientNum: " + details.getResObj().getClientNum());
    System.out.println("value of getServerNum: " + 
               details.getResObj().getServerNum());
    System.out.println("value of getIdNum: " + details.getResObj().getIdNum());
    System.out.println("value of getResInt: " + details.getResInt());

} }

**MyPojo Class:**

 public class MyPojo {
private ResObj resObj;

private String resInt;

public ResObj getResObj() {
    return resObj;
}

  public String getResInt() {
       return resInt;   } }

**ResObj class:**


public class ResObj {
private String serverNum;

private String idNum;

private String clientNum;

public String getServerNum() {
    return serverNum;
}

public String getIdNum() {
    return idNum;
}

public String getClientNum() {
    return clientNum;
} }

**RESULT**

  value of clientNum: 12345
  value of getServerNum: 78945
  value of getIdNum: 020252
  value of getResInt: 0

NOTE: I have removed Setters in classes & there is no effect on the result.
Atul KS
  • 908
  • 11
  • 21
0

I tried all the ways mentioned above but in my case, this is the only solution that worked as answered here Solution 2. Here I have enabled @EnableWebMvc in my spring boot application.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private ObjectMapper objectMapper;// created elsewhere
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // this will add a 2nd MappingJackson2HttpMessageConverter 
        converters.add(new MappingJackson2HttpMessageConverter(this.objectMapper));
    }
}
Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
-1

You need to define another class for the information within ResObj {"ClientNum":"12345","ServerNum":"78945","IdNum":"020252"}. Otherwise jackson cannot determine how to deserialize.

  • well i did, i called it ResObj, which has the wanted fields, but it still not working, i mean: public class Response { private ResObj resObj; public ResObj getResObj() { return resObj; } .... public class ResObj { private String ClientNum; private String ServerNum; private String IdNum; public String getClientNum() { return ClientNum; } public String getServerNum() { return ServerNum; } public String getIdNum() { return IdNum; } } – user2212726 May 05 '14 at 10:22