【问题标题】:How to enable POJO mapping for Java 8 Instant class?如何为 Java 8 Instant 类启用 POJO 映射?
【发布时间】:2019-11-13 10:41:48
【问题描述】:

我有一个StartupListener,它注册了JavaTime 模块。但我仍然收到错误

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
@WebListener
public class StartupListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        logger.log(Level.CONFIG, "servlet content initialized");
        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.findAndRegisterModules();
        JavaTimeModule module = new JavaTimeModule();
        objectMapper.registerModule(module);
    }
}

我正在使用启用了 POJOMapping 的 Jersy。我的模型类有 Instant dateCreated; 失败。我的依赖是:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.19</version>
</dependency>
...
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.10.0</version>
</dependency>

如何解决这个问题?


@JsonIgnoreProperties(ignoreUnknown = true)
public class ProductDTO {
    private String name;
    private String description;

    private String mrp;
    private String price;
    private String savePrice;

    private String url;
    private String imageURL;
    private String ratings;
    private String ratingsCount;

    private Instant dateCreated;

    public Instant getDateCreated() {
        return dateCreated;
    }

    public void setDateCreated(Instant dateCreated) {
        this.dateCreated = dateCreated;
    }

   // ..


我已经添加了lombok 依赖项并按照答案中的说明进行了注释,但我仍然遇到同样的错误。请查找错误日志:

[INFO] GCLOUD: Nov 14, 2019 12:29:42 PM com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
[INFO] GCLOUD: SEVERE: The exception contained within MappableContainerException could not be mapped to a response, re-throwing to the HTTP container
[INFO] GCLOUD: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
[INFO] GCLOUD:  at [Source: (org.eclipse.jetty.server.HttpInputOverHTTP); line: 1, column: 1245] (through reference chain: com.proto.model.ProductDTO["dateModified"])
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1055)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1682)
[INFO] GCLOUD:  at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:977)
[INFO] GCLOUD:  at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:814)
[INFO] GCLOUD:  at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:490)
[INFO] GCLOUD:  at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123)

我正在使用自定义值填充 ProductDTO,并将其作为 POST 发送到作为应用引擎任务工作者的休息端点。

ProductDTO {
name = "8X (Black, 4GB RAM, 64GB Storage)"
description = ""
mrp = "7,999.00"
price = ""
url = ""
imageURL = ""
ratings = "4.4"
ratingsCount = "5,910"
dateCreated = {Date@7067} "Thu Nov 14 12:41:14 IST 2019"
dateModified = {Instant@9346} "2019-11-14T07:12:47.255Z"
}

接受这个dto的端点是

@POST
@Path("/transform")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public WorkerResponse transform(ProductDTO dto) throws IOException {
    // ...
}

这会导致映射失败。

【问题讨论】:

  • 请展示你的模特课
  • 这是一个普通的 POJO 类,带有@JsonIgnoreProperties(ignoreUnknown = true)
  • 我打赌你的字段没有getters/setters
  • 我已经用模型更新了问题。

标签: java jackson date jersey-1.0


【解决方案1】:

首先,确保您的 Json 节点具有正确的名称 - dateCreated。 然后确保你有默认的@NoArgsConstructor/@AllArgsConstructor 辅导员。 尝试使用以下内容修改您的ObjectMapper

ObjectMapper mapper = new ObjectMapper().findAndRegisterModules().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

Jackson 默认将Instant 取消实现为时间戳,因此您需要禁用它。

lombok注解的使用:

  @AllArgsConstructor
     @NoArgsConstructor
     @Data
     @JsonIgnoreProperties(ignoreUnknown = true)
public class ProductDTO {
...
}

【讨论】:

  • 这不起作用,我遇到了同样的错误。我不确定在哪里放置 NoArgsConstructor 注释。我没有使用 Lombok。
  • @jsloop 这是类级别的注释。你应该把它放在你的班级 pojo 上。喜欢:@JsonIgnoreProperties(ignoreUnknown = true) @NoArgsConstructor public class ProductDTO { ... }
  • 我应该包含哪些依赖项才能获得此注释?我收到Cannot resolve symbol NoArgConstructor
  • @jsloop import lombok.NoArgsConstructor; 我也编辑了我的答案
  • 我已经添加了部门,但得到了同样的异常。我怀疑 Jackson 没有接受对象映射器注册。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多