没有从字符串值反序列化的字符串参数构造函数/工厂方法('2018-12-14')

Posted

技术标签:

【中文标题】没有从字符串值反序列化的字符串参数构造函数/工厂方法(\'2018-12-14\')【英文标题】:no String-argument constructor/factory method to deserialize from String value ('2018-12-14')没有从字符串值反序列化的字符串参数构造函数/工厂方法('2018-12-14') 【发布时间】:2019-05-15 06:10:24 【问题描述】:

这个问题与this 几乎相同,但不同之处在于我试图将字符串转换为LocalDate。这是来自 STS 的错误:

2018-12-14 00:47:04.507 警告 6216 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver :已解决 [org.springframework.http.converter.HttpMessageNotReadableException: JSON 解析错误:无法构造 java.time.LocalDate 的实例: 没有要反序列化的字符串参数构造函数/工厂方法 字符串值('2018-12-14');嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:无法构造 java.time.LocalDate 的实例:没有字符串参数 从字符串值反序列化的构造函数/工厂方法 ('2018-12-14')在 [来源:java.io.PushbackInputStream@73ff9989; 行:3,列:16](通过参考链: com.xxxxx.xxxxxx.model.request.ReservationRequest["checkin"])]

这是来自 Postman:

时间戳”:1544744824516, “状态”:400, "error": "错误请求", “异常”:“org.springframework.http.converter.HttpMessageNotReadableException”, “消息”:“JSON 解析错误:无法构造 java.time.LocalDate 的实例:没有字符串参数构造函数/工厂方法 从字符串值反序列化('2018-12-14');嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:无法构造 java.time.LocalDate 的实例:没有字符串参数 从字符串值反序列化的构造函数/工厂方法 ('2018-12-14')\n 在 [来源:java.io.PushbackInputStream@73ff9989; 行:3,列:16](通过参考链: com.xxxxx.xxxxx.model.request.ReservationRequest[\"checkin\"])", "路径": "/room/reservation/v1"

POST 请求是:


    "id": 12345,
    "checkin": "2018-12-14",
    "checkout": "2018-12-17"

相关类是:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
public class ApiConfig 

    @Bean
    public ObjectMapper objectMapper() 
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        return new ObjectMapper();
    

    @Bean
    public ObjectWriter objectWriter(ObjectMapper objectMapper) 
        return objectMapper.writerWithDefaultPrettyPrinter();
    

import java.time.LocalDate;
import org.springframework.format.annotation.DateTimeFormat;

public class ReservationRequest 

    private Long id;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate checkin;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate checkout;

    public ReservationRequest() 
        super();
    

    public ReservationRequest(Long id, LocalDate checkin, LocalDate checkout) 
        super();
        this.id = id;
        this.checkin = checkin;
        this.checkout = checkout;
    

    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public LocalDate getCheckin() 
        return checkin;
    

    public void setCheckin(LocalDate checkin) 
        this.checkin = checkin;
    

    public LocalDate getCheckout() 
        return checkout;
    

    public void setCheckout(LocalDate checkout) 
        this.checkout = checkout;
    

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.xxxxx.xxxxxx.model.request.ReservationRequest;
import com.xxxxx.xxxxxx.model.response.ReservationResponse;

@RestController
@RequestMapping(ResourceConstants.ROOM_RESERVATION_V1)
public class ReservationResource 

    @RequestMapping(path = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<ReservationResponse> getAvaiableRooms(
            @RequestParam(value = "checkin") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate checkin,
            @RequestParam(value = "checkout") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate checkout) 
        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    

    @RequestMapping(path = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<ReservationResponse> createReservation(@RequestBody ReservationRequest reservationRequest) 

        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.CREATED);
    

    @RequestMapping(path = "", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<ReservationResponse> updateReservation(@RequestBody ReservationRequest reservationRequest) 

        return new ResponseEntity<>(new ReservationResponse(), HttpStatus.OK);
    

    @RequestMapping(path = "/reservationId", method = RequestMethod.DELETE)
    public ResponseEntity<Void> deleteReservation(@PathVariable long reservationId) 

        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    

我已包含导入以防万一。

无论如何,如果我将 ReservationRequest 更改为具有字符串而不是 LocalDate 的字段,那么它不会产生错误

public class ReservationRequest 

    private Long id;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private String checkin;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private String checkout;

    public ReservationRequest() 
        super();
    

    public ReservationRequest(Long id, String checkin, String checkout) 
        super();
        this.id = id;
        this.checkin = checkin;
        this.checkout = checkout;
    

(getters and setters updated as well)

JDK 1.8; springBootVersion = '1.5.17.RELEASE';名称:'jackson-datatype-jsr310',版本:'2.9.7'

问题是为什么它不能按预期使用 LocalDate

更新:尝试了these 解决方案,并添加了@JsonSerialize 和@JsonDeserialize,因为objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 都没有 或objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

工作,所以现在看起来像:

public class ReservationRequest 

    private Long id;
    @JsonSerialize(using = ToStringSerializer.class)
    @JsonDeserialize(using = LocalDateDeserializer.class)
    //@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate checkin;
    @JsonSerialize(using = ToStringSerializer.class)
    @JsonDeserialize(using = LocalDateDeserializer.class)
    //@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate checkout;

    public ReservationRequest() 
        super();
    

所以,现在看起来可行,但我不知道这是否是一个好的解决方案?

【问题讨论】:

FasterXML/jackson-modules-java8: Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names) 试过了 - 没有帮助。 【参考方案1】:

我认为问题出在这里

@Bean
public ObjectMapper objectMapper() 
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    return new ObjectMapper();

您必须返回已配置的 objectMapper 而不是新实例:

@Bean
public ObjectMapper objectMapper() 
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
    objectMapper.registerModule(new JavaTimeModule()
            .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("M/d/yyyy")))
            .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("M/d/yyyy"))))
    return objectMapper;

【讨论】:

【参考方案2】:

我最近遇到了同样的问题,错误的原因是我的 json 字符串周围有双引号,当我删除它时它工作得很好

【讨论】:

【参考方案3】:

我认为现在回复帖子为时已晚,我遇到了同样的问题,下面的注释很有帮助。

@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate dateOfBirth;

:)

【讨论】:

以上是关于没有从字符串值反序列化的字符串参数构造函数/工厂方法('2018-12-14')的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot:没有从字符串值反序列化的字符串参数构造函数/工厂方法

objectmapper.readValue() 失败并出现错误“没有从字符串值反序列化的字符串参数构造函数/工厂方法”

使用 Jackson 从 XML 到 POJO 的反序列化问题:没有从字符串值反序列化的字符串参数构造函数/工厂方法

openapi springboot generator jackson no String-argument构造函数/工厂方法从字符串值反序列化

没有从字符串值('1074')反序列化的字符串参数构造函数/工厂方法

com.fasterxml.jackson.databind.JsonMappingException 没有从字符串值('1')反序列化的字符串参数构造函数/工厂方法