5

I'm trying to use modelmapper to map my Class with the incoming request.

It looks like Date is not able to auto convert in modelmapper.

Converter org.modelmapper.internal.converter.DateConverter@7595415b failed to convert java.lang.String to java.util.Date. Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:

The above is the exception which is get.

So how to skip this Date field alone

Currently My code looks like,

ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
MyClass obj=mapper.map(anotherObject,MyClass.class);

MyClass

public class MyClass {

    int id;

    Date updated_at;

}

anotherObject.toString

{id=6,updated_at=2018-02-23T03:01:12}

UPDATE 2

Apologies for the misguiding here.Actually, my anotherObject is not a class object. I'll explain my exact scenario below

My API response

{
    "rows": 1,
    "last": null,    
    "results": [
        {
            "id": "1",
            "updated_at;": "2018-01-22T13:00:00",
        },
        {
            "id": "2",
            "updated_at;": "2018-01-22T13:00:00",
        }

                ]
}

MysuperClass

public class MysuperClass {

    int rows;

    String last;

    List<Object> results;

}

Getting the response body using rest template

ResponseEntity<MysuperClass > apiResponse = restTemplate.exchange(Url, HttpMethod.GET, entity, MysuperClass .class)

MysuperClass anotherObject=apiResponse.getBody();

Actual Class

ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
    for (int index = 0; index < anotherObject.getResults().size(); index++) {

    MyClass obj=mapper.map(anotherObject.getResults().get(index),MyClass.class);

    }
Jayendran
  • 9,638
  • 8
  • 60
  • 103

3 Answers3

2

If you look at the model mapper source code for DateConverter it seems to only support java.sql.Date, java.sql.Time and java.sql.Timestamp classes as the destination type. And even then it only supports a very specific format of the source string in each case.

From model mapper DateConverter:

Date dateFor(String source, Class<?> destinationType) {
String sourceString = toString().trim();
if (sourceString.length() == 0)
  throw new Errors().errorMapping(source, destinationType).toMappingException();

if (destinationType.equals(java.sql.Date.class)) {
  try {
    return java.sql.Date.valueOf(source);
  } catch (IllegalArgumentException e) {
    throw new Errors().addMessage(
        "String must be in JDBC format [yyyy-MM-dd] to create a java.sql.Date")
        .toMappingException();
  }
}

if (destinationType.equals(Time.class)) {
  try {
    return Time.valueOf(source);
  } catch (IllegalArgumentException e) {
    throw new Errors().addMessage(
        "String must be in JDBC format [HH:mm:ss] to create a java.sql.Time")
        .toMappingException();
  }
}

if (destinationType.equals(Timestamp.class)) {
  try {
    return Timestamp.valueOf(source);
  } catch (IllegalArgumentException e) {
    throw new Errors().addMessage(
        "String must be in JDBC format [yyyy-MM-dd HH:mm:ss.fffffffff] "
            + "to create a java.sql.Timestamp").toMappingException();
  }
}

throw new Errors().errorMapping(source, destinationType).toMappingException();

}

So, the simplest fix would be to:

(1) change MyClass to use java.sql.Date instead of java.util.Date; but, if the time is important then use Timestamp

(2) modify the format of the date in your JSON to be acceptable to what Timestamp is expecting

Having said that, another option would be to work with the model mapper team to add support for java.util.Date, or better yet, the newer LocalDate or LocalDateTime. Or if you're interested you could also add the support yourself and submit a pull request. I may take a look at that this evening if I have time.

Hope this helps.

Russ Jackson
  • 1,993
  • 1
  • 18
  • 14
1

Can you try the following:

Create a new class Result to map the elements of the JSON results array into.

class Result {
  int id;
  String updated_at;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  // setter should take a string (as it is in the JSON)
  public void setUpdated_at(String updated_at) {
    this.updated_at = updated_at;
  }

  // the getter should return a Date to map with MyClass
  public Date getUpdated_at() {
    Date d = null;
    try {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
      d = format.parse(updated_at);
    } catch(ParseException e) {
      e.printStackTrace();
    }
    return d;
  }
}

Change your MysuperClass and make results a List of Result

List<Result> results;

And then try the following code:

ResponseEntity<MysuperClass > apiResponse = restTemplate.exchange(Url, HttpMethod.GET, entity, MysuperClass .class)
MysuperClass anotherObject = apiResponse.getBody(); // I hope that works fine

ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
for(Result result : anotherObject.getResults()) {
  MyClass obj = modelMapper.map(result, MyClass.class);
  System.out.println(obj.getId());
  System.out.println(obj.getUpdated_at());
}
Bentaye
  • 9,403
  • 5
  • 32
  • 45
  • Thanks for your answer. the anotherobject is not a class object(directly) Please see my **UPDATE 2**. please help me to handle this kind of mapping in such case. – Jayendran Feb 26 '18 at 13:09
  • I edited my answer, hopefully this works. Only unknown is if the `MysuperClass anotherObject=apiResponse.getBody();` will map correctly into the `Result` objects of the list inside your `MysuperClass`. If yes then it should work – Bentaye Feb 26 '18 at 13:53
0

Instead of focusing modelmapper alone.I forget to lookout other libraries for my usecase.

I found an easy approach using ObjectMapper(org.codehaus.jackson.map.ObjectMapper)

    List<<Result> results=(List<Result>)(Object)anotherObject.getResults();

    for(Object myObject: results){
        ObjectMapper objectMapper=new ObjectMapper();
        Appointment appointment= objectMapper.convertValue(myObject, MyClass.class);
    }
Jayendran
  • 9,638
  • 8
  • 60
  • 103