I am getting an error - 'Class com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer has no default (no arg) constructor' while I am trying to call restangular for post request. When I call the method it goes in the error block.
Restangular.all('tests').post($scope.test).then(function (data) {
$scope.test.id = data.id;
$location.path($location.path() + data.id).replace();
}, function (error) {
$scope.exceptionDetails = validationMapper(error);
});
I am using jackson-datatype-joda - 2.6.5
The entity class used in this method as follows -
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Entity
@Table(name = "Test")
@EqualsAndHashCode(of = "id", callSuper = false)
@ToString(exclude = {"keywords", "relevantObjectIds"})
public class Test {
@Id
@Column(unique = true, length = 36)
private String id;
@NotBlank
@NotNull
private String name;
@Transient
private List<Testabc> Testabcs = new ArrayList<>();
}
The entity class used in above entity Testabc class as follows
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Slf4j
@Entity
@Table(name = "Test_abc")
@EqualsAndHashCode(of = "id", callSuper = false)
public class Testabc{
@Id
@Column(unique = true, length = 36)
@NotNull
private String id = UUID.randomUUID().toString();
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@JsonDeserialize(using = DateTimeDeserializer.class)
@JsonSerialize(using = DateTimeSerializer.class)
private DateTime createdOn;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "Id")
@NotNull
private t1 pid;
private long originalSize;
}
Finally resource class where I am requesting to create test data -
@ApiOperation(value = "Create new Test", notes = "Create a new Test and return with its unique id", response = Test.class)
@POST
@Timed
public Test create(Test newInstance) {
return super.create(newInstance);
}
I have tried to add this @JsonIgnoreProperties(ignoreUnknown = true) annotation on entity class, but it doesn't work.
Can anyone help to resolve this problem?
Looking at the latest sources of DateTimeDeserializer
you can easily see that it does not have a no-arg constructor, which seems to be required by the framework. This is also indicated in both the linked questions: joda.time.DateTime deserialization error & Jackson, Retrofit, JodaTime deserialization
Since you want to use only an annotation based solution, a possible workaround would be to create your own deserializer which extends the DateTimeDeserializer
and provides a nor-arg constructor.
1) MyDateTimeSerializer
import com.fasterxml.jackson.datatype.joda.cfg.FormatConfig;
import com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer;
import org.joda.time.DateTime;
public class MyDateTimeDeserializer extends DateTimeDeserializer {
public MyDateTimeDeserializer() {
// no arg constructor providing default values for super call
super(DateTime.class, FormatConfig.DEFAULT_DATETIME_PARSER);
}
}
2) AClass
using the custom deserializer
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
public class AClass {
@JsonSerialize(using = DateTimeSerializer.class) // old serializer
@JsonDeserialize(using = MyDateTimeDeserializer.class) // new deserializer
private DateTime createdOn = DateTime.now(DateTimeZone.UTC); // some dummy data for the sake of brevity
public DateTime getCreatedOn() {
return createdOn;
}
public void setCreatedOn(DateTime createdOn) {
this.createdOn = createdOn;
}
}
3) Unit test
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class ATest {
@Test
public void testSomeMethod() throws Exception {
// Jackson object mapper to test serialization / deserialization
ObjectMapper objectMapper = new ObjectMapper();
// our object
AClass initialObject = new AClass();
// serialize it
String serializedObject = objectMapper.writeValueAsString(initialObject);
// deserialize it
AClass deserializedObject = objectMapper.readValue(serializedObject, AClass.class);
// check that the dates are equal (no equals implementation on the class itself...)
assertThat(deserializedObject.getCreatedOn(), is(equalTo(initialObject.getCreatedOn())));
}
}
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