【问题标题】:DateConverter failed to convert java.lang.String to java.util.Date. Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:DateConverter 无法将 java.lang.String 转换为 java.util.Date。引起:org.modelmapper.MappingException:ModelMapper映射错误:
【发布时间】:2018-02-23 12:35:59
【问题描述】:

我正在尝试使用 modelmapper 将我的 Class 与传入的请求进行映射。

Date 似乎无法在 modelmapper 中自动转换。

转换器 org.modelmapper.internal.converter.DateConverter@7595415b 未能将 java.lang.String 转换为 java.util.Date。造成的: org.modelmapper.MappingException:ModelMapper 映射错误:

以上是get的异常。

那么如何单独跳过这个日期字段

目前我的代码看起来像,

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

我的班级

public class MyClass {

    int id;

    Date updated_at;

}

anotherObject.toString

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

更新 2

对这里的误导表示歉意。实际上,我的 anotherObject 不是类对象。我将在下面解释我的确切情况

我的 API 响应

{
    "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;

}

使用rest模板获取响应正文

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

MysuperClass anotherObject=apiResponse.getBody();

实际类

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);

    }

【问题讨论】:

  • 请提供 My class 和 anotherObject 的结构。
  • @Bentaye 更新
  • 这可能是一个长镜头,但 JSON 规范要求将字符串包裹在 "" (这是您的日期字段)中,并且由于您启用了 STRICT,它可能会抱怨 JSON 格式无效。

标签: java spring api modelmapper


【解决方案1】:

如果您查看model mapper source code for DateConverter,它似乎只支持 java.sql.Date、java.sql.Time 和 java.sql.Timestamp 类作为目标类型。即便如此,它在每种情况下也只支持非常特定的源字符串格式。

来自模型映射器 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();

}

因此,最简单的解决方法是:

(1) 将 MyClass 更改为使用 java.sql.Date 而不是 java.util.Date;但是,如果时间很重要,请使用时间戳

(2) 修改 JSON 中的日期格式,使其符合 Timestamp 的预期

话虽如此,另一种选择是与模型映射器团队合作以添加对 java.util.Date 的支持,或者更好的是,更新的 LocalDate 或 LocalDateTime。或者,如果您有兴趣,您也可以自己添加支持并提交拉取请求。今晚有空的话,我可能会看一下。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以尝试以下方法:

    创建一个新类Result 将JSON results 数组的元素映射到。

    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;
      }
    }
    

    更改您的 MysuperClass 并使 results 成为结果列表

    List<Result> results;
    

    然后试试下面的代码:

    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());
    }
    

    【讨论】:

    • 感谢您的回答。 anotherobject 不是类对象(直接)请参阅我的 UPDATE 2。在这种情况下,请帮我处理这种映射。
    • 我编辑了我的答案,希望这可行。唯一未知的是MysuperClass anotherObject=apiResponse.getBody(); 是否会正确映射到MysuperClass 内列表的Result 对象。如果是,那么它应该可以工作
    【解决方案3】:

    而不是单独关注模型映射器。我忘记为我的用例寻找其他库。

    我发现了一个使用 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);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多