【问题标题】:'@RequiredArgsConstructor' and 'MismatchedInputException: Cannot construct instance'“@RequiredArgsConstructor”和“MismatchedInputException:无法构造实例”
【发布时间】:2020-05-05 20:38:16
【问题描述】:

我有多个看起来像这样的 DTO 对象:

@Getter
@RequiredArgsConstructor
public class SomeDTO {
  private final String someProperty;
}

这些 DTO 对象在各种 RestController 方法中被接受:

@RestController
public void InvitationController {

  @PostMapping
  public String create(@RequestBody InvitationCreationDTO invitationCreationDTO) {
    // some logic
    return "ok";
  }

}

Jackson 将 json 反序列化为这些类没有问题,除了以下一个:

@Getter
@RequiredArgsConstructor
public class InvitationCreationDTO {
  private final String emailAddress;
}

当 Jackson 尝试反序列化以下 JSON 时:

{ "emailAddress" : "some@email.com" }

抛出此错误:

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `my.package.InvitationCreationDTO` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (PushbackInputStream); line: 1, column: 2]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1429) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1059) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3258) ~[jackson-databind-2.10.2.jar:2.10.2]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
    ... 86 common frames omitted

但是,当我删除 @RequiredArgsConstructor 并自己创建一个时,它可以工作:

@Getter
public class InvitationCreationDTO {
  private final String emailAddress;

  @JsonCreator
  public InvitationCreationDTO(String emailAddress) {
    this.emailAddress = emailAddress;
  }
}

为什么这个类需要这个,而我的其他 DTO 类(具有相同格式)却不需要?

【问题讨论】:

  • 尝试添加另一个@NoArgsConstructor(force = true, access = PRIVATE)
  • 我会试试看,但是杰克逊为什么不抱怨其他看起来像这样的 DTO 类?
  • 如果无法访问您的代码库,我确实有点不知所措:/ 我猜用法有点不同?您是否以完全相同的方式使用两个 DTO,例如通过@RequestBody,相同的请求Content-Type,相同的ObjectMapper,等等?
  • @sp00m,是的,所有 DTO 对象都以相同的方式使用。我有很多 SomeCreationDTO 类都可以正常工作,除了这个。

标签: java spring-mvc jackson spring-restcontroller


【解决方案1】:

尝试将@NoArgsConstructor 添加到您的InvitationCreationDTO 课程中

@Getter
@NoArgsConstructor
@RequiredArgsConstructor
public class InvitationCreationDTO {
  private final String emailAddress;
}

【讨论】:

  • @NoArgsConstructor 添加到具有final 字段的类不起作用。
  • 你的意思是不行? @NoArgsConstructor 创建带有空参数的构造函数。它不关心你有多少最终/非最终字段。
  • 实际上为什么它是最终的,您是否尝试删除最终?
  • 标记为final 的属性需要在实例化时进行初始化。无参数构造函数不会实例化它,这就是编译器在添加此注释时抱怨的原因。字段是最终的,因为类是不可变的。
  • @GigaKokaia 完成字段是一个很好的做法,它允许不变性,这本身就解决了许多其他问题 :) 您可以强制使用 @NoArgsConstructor(force = true)。我不记得这个的确切输出,一定是相当hacky,但我记得它解决了我遇到的类似问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
  • 2021-07-17
  • 1970-01-01
  • 2014-08-28
  • 2020-09-27
相关资源
最近更新 更多