No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator
Reason: This error occurs because jackson library doesn't know how to create your model which doesn't have an empty constructor and the model contains constructor with parameters which didn't annotated its parameters with @JsonProperty("field_name")
. By default java compiler creates empty constructor if you didn't add constructor to your class.
Solution:
Add an empty constructor to your model or annotate constructor parameters with @JsonProperty("field_name")
If you use a Kotlin data class then also can annotate with @JsonProperty("field_name")
or register jackson module kotlin to ObjectMapper
.
You can create your models using http://www.jsonschema2pojo.org/.
No Creators Exist: Cannot Deserialize
If there is no constructors that is annotated with @JsonCreator
, by default, Jackson needs a default no-args constructor in order to parse the JSON into POJO or bean classes. That is why when you add a default constructor, it will work fine.
And if you don't actually need the usage of the default constructor, just add it for Jackson only, you can set it to private
, protected
or package-protected
. Jackson is still able to fill all the fields via reflection.
Regarding the no delegate- or property-based Creator
, they are constructors that is annotated with @JsonCreator
. In Jackson, there are 2 types of Creator/JsonCreator which are delegate-based Creator
and property-based Creator
.
Delegate-based creators take just one argument, which is NOT annotated with @JsonProperty. Type of that property is used by Jackson to bind the whole JSON value (JSON Object, array or scalar value), to be passed as value of that one argument.
Property-based creators take one or more arguments; all of which MUST be annotated with @JsonProperty, to specify JSON name used for property. They can only be used to bind data from JSON Objects; and each parameter represents one property of the JSON Object; type of property being used for binding data to be passed as that parameter when calling creator.
You can read for more details about these 2 creators in the article below.
http://www.cowtowncoder.com/blog/archives/2011/07/entry_457.html
Cannot deserialize from Object value (no delegate- or property-based Creator) using Jackson
You have to consider few cases:
message
field inJSON
is primitiveString
. OnPOJO
level it is anMessageSubscription
object.message
value inJSON
contains unquoted property names which is illegal butJackson
handles them as well.- If constructor does not fit to
JSON
we need to configure it using annotations.
To handle unquoted names we need to enable ALLOW_UNQUOTED_FIELD_NAMES feature. To handle mismatch between JSON
payload and POJO
we need to implement custom deserialiser for MessageSubscription
class.
Custom deserialiser could look like this:
class MessageSubscriptionJsonDeserializer extends JsonDeserializer<MessageSubscription> {
@Override
public MessageSubscription deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
final String value = p.getValueAsString();
final Map<String, String> map = deserializeAsMap(value, (ObjectMapper) p.getCodec(), ctxt);
return new MessageSubscription(map.get("Message"), map.get("SubscriptionUID"));
}
private Map<String, String> deserializeAsMap(String value, ObjectMapper mapper, DeserializationContext ctxt) throws IOException {
final MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, String.class);
return mapper.readValue(value, mapType);
}
}
Now, we need to customise DeserializeSubscription
's constructor:
@Data
class DeserializeSubscription {
private String code;
private String reason;
private MessageSubscription message;
@JsonCreator
public DeserializeSubscription(
@JsonProperty("code") String code,
@JsonProperty("reason") String reason,
@JsonProperty("message") @JsonDeserialize(using = MessageSubscriptionJsonDeserializer.class) MessageSubscription message) {
super();
this.code = code;
this.reason = reason;
this.message = message;
}
}
Example how to use it:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.MapType;
import lombok.Data;
import java.io.File;
import java.io.IOException;
import java.util.Map;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
DeserializeSubscription value = mapper.readValue(jsonFile, DeserializeSubscription.class);
System.out.println(value);
}
}
For provided JSON
payload above example prints:
DeserializeSubscription(code=null, reason=subscription yet available, message=MessageSubscription(message=subscription yet available, subscriptionUID=46b62920-c519-4555-8973-3b28a7a29463))
Cannot construct instance of `com.domain.User` (no Creators, like default constructor, exist): cannot deserialize from Object value
I could reproduce the exception. Then I added an all-args constructor with each parameter annotated with the right @JsonProperty
.
@JsonCreator
public User(
@JsonProperty("email") String email,
@JsonProperty("password") String password,
@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("gender") String gender,
@JsonProperty("registrationTime") Instant registrationTime){
super();
this.email = email;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.registrationTime = registrationTime;
}
Now, it creates the instance, but I get other mapping errors (Unrecognized field "given_name") which you should be able to resolve.
Related Topics
Open Play Store App from Browser Link
Illegalstateexception: Link Does Not Have a Navcontroller Set
Link Should Be Open in Same Web View in Android
Android: How to Propagate Click Event to Linearlayout Childs and Change Their Drawable
How to Show List of String in Textview on Android
How to Display a Loading Spinner While Getting Data from Firestore
How to Know When My App Has Been Killed
How to Disable Edittext in Android
Chrome on Android Resizes Font
How to Completely Rename an Android Application
How to Set Android_Ndk_Home So That Android Studio Does Not Ask for Ndk Location
How to Disable Recyclerview Items from Clicking
Android Refresh a Fragment List from Its Parent Activity
How to Reduce the Gap Between Tab Layout Text and Its Indicator
How to Open Fragment from Recyclerview Adapter