Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - JsonMappingException due to constructor

I am having the following exception when trying to deserialize a JSON

No suitable constructor found for type [simple type, class MyObj$obj$Card]: can not instantiate from JSON object (need to add/enable type information?) at [Source: java.io.StringReader@4344ee21; line: 1, column: 201] (through reference chain: MyObj["obj"]->Obj["cards"])

And the JSON is

{   "obj":{   "api":"OK",   "cache":false,   "cards":[      {         "id":1232995897,         "items":[            {               "id":"vmdSJLpnY",               "cat":50,               "rating":0.0            }         ]      },      {         "id":0005897,         "items":[            {               "id":"vxdSJLpnY",               "cat":50,               "rating":0.0            }         ]      }  ]  } } 

And within the Obj class I have the following statement

@JsonProperty("cards") private Card[] cards;

Which produces the exception above. Changing the type Card[] to Object[] does not produce an exception, but it lacks of the correct mapping I desire to get.

Any clue how can I resolve it? A snippet will be GREAT! What this error means anyhow?

UPDATE

I have included the Java class.

import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.Gson;  @JsonIgnoreProperties(ignoreUnknown=true) public final class MyObj {     @JsonIgnoreProperties(ignoreUnknown=true)     public final class Obj {         @JsonIgnoreProperties(ignoreUnknown=true)         public final class Card {             @JsonIgnoreProperties(ignoreUnknown=true)             public final class Item {                 @JsonProperty("id") private String id;                 @JsonProperty("cat") private String cat;                 @JsonProperty("rating") private String rating;                 public final String getId() { return id; }                 public final String getCat() { return cat; }                 public final String getRating() { return ranting; }                 public final String toString() { return new Gson().toJson(this); }             }              @JsonProperty("items") private Item[] items;             public final Item[] getItems() { return items; }             public final String toString() { return new Gson().toJson(this); }         }          @JsonProperty("cards") private Card[] cards;         public Card[] getCards() { return cards; }         public final String toString() { return new Gson().toJson(this); }           }       @JsonProperty("obj") MyObj obj;     public final Card[] getCards(){ return apiServiceResultsNoLists.getCards(); } } 
like image 818
Mr. Avatar asked Oct 11 '12 09:10

Mr.


People also ask

Does Jackson require no args constructor?

Jackson won't use a constructor with arguments by default, you'd need to tell it to do so with the @JsonCreator annotation. By default it tries to use the no-args constructor which isn't present in your class.

What does Jackson ObjectMapper do?

The Jackson ObjectMapper can parse JSON from a string, stream or file, and create a Java object or object graph representing the parsed JSON. Parsing JSON into Java objects is also referred to as to deserialize Java objects from JSON. The Jackson ObjectMapper can also create JSON from Java objects.

What is JSON mapping exception?

public class JsonMappingException extends JsonProcessingException. Checked exception used to signal fatal problems with mapping of content, distinct from low-level I/O problems (signaled using simple IOException s) or data encoding/decoding problems (signaled with JsonParseException , JsonGenerationException ).

Does Jackson ObjectMapper use reflection?

Jackson is a framework that provides the means to read and write objects to and from JSON. Typically, it tries to use built in support for common classes and simple types. It will also use a default serializer based on reflection to write the JSON, but will need some guidance for more complex custom objects.


1 Answers

I think the problem is most likely with the Card object

  • it might not have a default constructor
  • if it doesn't have a default constructor, it should be annotated using @JsonCreator

EDIT I have two things:
* you don't have setters.
* you don't have a public constructor that would be allowed to set your fileds.

How should the deserializer populate your fields if you don't give it any (legal*) means for it?

Solutions:
-> add public setters to the classes
-> or create parametrized constructors annotated with @JsonCreator

*: of course, the parser could do the reflective "mofidy the visibility" trick, but come on, this is not "the way it's meant to be played"

EDIT2 I think this should work, but I can't test it - I don't have a project at hand with Jackson properly set up now (this is just a part of it, but I think it is easy to interpret what I wanted to show.) Note, I changed the array to a List:

    @JsonIgnoreProperties(ignoreUnknown=true)      public final class Card {          @JsonIgnoreProperties(ignoreUnknown=true)      public final class Item {              @JsonProperty("id") private String id;              @JsonProperty("cat") private String cat;              @JsonProperty("rating") private String rating;               @JsonCreator         public Item(@JsonProperty("id") String id, @JsonProperty("cat") String cat, @JsonProperty("rating") String rating) {             this.id = id;             this.cat = cat;             this.rating = rating;         }              public final String getId() { return id; }              public final String getCat() { return cat; }              public final String getRating() { return ranting; }              public final String toString() { return new Gson().toJson(this); }          }          @JsonProperty("items") private List<Item> items;           @JsonCreator     public Card(@JsonProperty("items") List<Item> items) {         this.items = items;     }             public final List<Item> getItems() { return items; }           public final String toString() { return new Gson().toJson(this); }      }      
like image 141
ppeterka Avatar answered Sep 21 '22 04:09

ppeterka