Ash Ash - 9 months ago 76
Java Question

Cannot deserialize custom Date object with Jackson in Springboot "no single-String constructor/factory method"


In an effort to clarify the issue I've made a diagram:

enter image description here

I've been migrating custom Jetty web services to use the Spring REST Templates and I've ran into an issue with the following deserializer.

The custom-date format comes back like so:

and I need to transform that into 3 integers before calling a constructor of this custom

Previously this was working because we just passed the service an
with the deserializer registered and it called
with no issues.

Now however I'm getting an error because Jackson attempts to call a
constructor on my custom
type which doesn't exist. This library is not maintained by me and therefore I cannot add this constructor.


"Failed to read HTTP message:
Could not read document: Can not instantiate value of type [simple
type, class] from String value
('2016-09-30'); no single-String constructor/factory method


Annotating the attribute that I am attempting to serialize works, but I do not consider this to be a solution because registering the deserialiser should detect the type and call itself. I'm more interested in why this is not working than switching to annotations:

private Date paymentDate;

I have the following Spring config:

public class WebServiceConfig {

private MappingJackson2HttpMessageConverter jacksonConverter;

public MyWebService MyWebService () {
RestTemplate restTemplate = new RestTemplate();
return new MyWebService(restTemplate);


public class JacksonConfig {

public MappingJackson2HttpMessageConverter jacksonConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
return converter;

public ObjectMapper objectMapper() {
Jackson2ObjectMapperBuilder mapperBuilder = new Jackson2ObjectMapperBuilder();

public Module myModule() {
SimpleModule module = new SimpleModule("myModule", new Version(0, 0, 1, null));

module.addSerializer(new CustomDateSerializer());
//not Java Date - custom Date...
module.addDeserializer(Date.class, new CustomDateDeserializer());

return module;

// breakpoints indicate this is never called
static public class CustomDateDeserializer extends JsonDeserializer<Date> {

public Date deserialize(JsonParser jp, DeserializationContext ctxt) {
String text = jp.getText();
if (text == null) {
return null;
if (text.length() >= 10) {
int year = parseInt(text.substring(0, 4));
int month = parseInt(text.substring(5, 7));
int day = parseInt(text.substring(8, 10));
return new Date(year, month, day);
// deserialize json object
else if (JsonToken.START_OBJECT.equals(jp.getCurrentToken())) {
JsonNode dateNode = jp.getCodec().readTree(jp);
return getDate(dateNode);
else {
return new Date(Integer.parseInt(text));



import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

public class PensionPaymentStatus {

private boolean available;
private Money netMonthly;
//this date fails to deserialise
private Date paymentDate;
private boolean suspended;


Example JSON payload

"available": true,
"netMonthly": "1000.00",
"paymentDate": "2016-10-19",
"suspended": false

The date class is huge and just wraps Joda time (used in pre-Java8 envs). It has several constructors, the one I'm trying to use is a YYYY, MM, DD integer constructor.

Answer Source

It seems like request is not being deserialized by your converter.

RestTemplate`s no-arg constructor initializes it with default converters, relevant snippet:

if (jackson2Present) {
    this.messageConverters.add(new MappingJackson2HttpMessageConverter());

And since it uses 'first one wins' strategy to find appropriate converter it will never use yours because it is positioned later in the list.

You need to change:

RestTemplate restTemplate = new RestTemplate();

To something like this:

RestTemplate restTemplate = new RestTemplate(Collections.singletonList(jacksonConverter));

Depending on whether you need additional converters or not.