First off, I am aware of this question: CustomDeserializer has no default (no arg) constructor
I have used the recommended solution, but have still the same problem. When I try to deserialize my json, I still get the error.
I want a custom deserialization of my object. My unit test looks the following:
Service service = new Service();
service.setId("ID");
service.setTitle("Title");
service.setDescription("Description");
service.setType("Service");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(service);
Service service2 = mapper.readValue(json, Service.class);
My Deserializer (contains some functionality currently not covered by the Unit test, but he is not even getting this far):
public class ServiceDeserializer extends StdDeserializer<Service> {
public ServiceDeserializer() {
super(Service.class);
}
@Override
public Service deserialize(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException {
DataBaseManagment manager = DataBaseManagmentManager.getInstance();
List<DataObject> objects = manager.readAll("Utility", true);
JsonNode node = jp.getCodec().readTree(jp);
String id = node.get("id").asText();
String title = node.get("title").asText();
String description = node.get("description").asText();
Service service = new Service(id, title, description);
for (JsonNode utility : node.get("provides")) {
String checkId = utility.get("id").asText();
for (DataObject object : objects) {
if (object.getId().equals(checkId)) {
service.addUtility((Utility) object);
break;
}
}
}
return service;
}
}
The binding:
@Entity
@Table(name = "SERVICE")
@JsonDeserialize(using = ServiceDeserializer.class)
public class Service extends DataObject {
...
}
The error stack:
com.fasterxml.jackson.databind.JsonMappingException: Class de.fraunhofer.fkie.aidpfm.reader.utils.JsonAdapter$ServiceDeserializer has no default (no arg) constructor
at [Source: (String)"{"pk":0,"id":"ID","title":"Title","description":"Description","type":"Service","provides":[],"fulfills":[],"ensures":[],"consistsOf":[],"partOf":[],"requires":[],"requiredBy":[],"classifiedBy":[]}"; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:305)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4178)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3997)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
at de.fraunhofer.fkie.aidpfm.model.JsonConvertionTest.jsonToObjectTest(JsonConvertionTest.java:123)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalArgumentException: Class de.fraunhofer.fkie.aidpfm.reader.utils.JsonAdapter$ServiceDeserializer has no default (no arg) constructor
at com.fasterxml.jackson.databind.util.ClassUtil.createInstance(ClassUtil.java:553)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.deserializerInstance(DefaultDeserializationContext.java:229)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findDeserializerFromAnnotation(DeserializerCache.java:427)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:326)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 30 more
How can I fix this problem? is there something wrong with the default constructor, or is the mistake somewhere else?
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.
No-Arg Constructor - a constructor that does not accept any arguments. Parameterized constructor - a constructor that accepts arguments. Default Constructor - a constructor that is automatically created by the Java compiler if it is not explicitly defined.
Considering de.fraunhofer.fkie.aidpfm.reader.utils.JsonAdapter$ServiceDeserializer
, ServiceDeserializer
seems to be an inner class of JsonAdapter
. Inner classes that are not static
can only be initialized like this:
JsonAdapter outerClass = new JsonAdapter();
ServiceDeserializer innerClass = outerClass.new ServiceDeserializer();
Whereas Jackson is probably trying to instantiate the class like (simplified, actually it's using Java Reflection API)
ServiceDeserializer sd = new JsonAdapter.ServiceDeserializer();
But this doesn't work because ServiceDeserializer
is an inner, non-static class. To simply resolve the issue, make ServiceDeserializer
static
.
public static class ServiceDeserializer extends StdDeserializer<Service>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With