JSON 以自定义格式序列化日期(无法从字符串值构造 java.util.Date 的实例)

Posted

技术标签:

【中文标题】JSON 以自定义格式序列化日期(无法从字符串值构造 java.util.Date 的实例)【英文标题】:JSON Serializing date in a custom format (Can not construct instance of java.util.Date from String value) 【发布时间】:2013-07-13 09:27:01 【问题描述】:
could not read JSON: Can not construct instance of java.util.Date from String 
value '2012-07-21 12:11:12': not a valid representation("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))

将 json 请求传递给 POJO 类中的 REST 控制器方法。用户应仅以低于日期时间格式输入,否则应抛出消息。为什么 DateSerializer 不调用?

add(@Valid @RequestBody User user)


json:


   "name":"ssss",
   "created_date": "2012-07-21 12:11:12"

pojo 类变量

@JsonSerialize(using=DateSerializer.class)
@Column
@NotNull(message="Please enter a date")      
@Temporal(value=TemporalType.TIMESTAMP)
private Date created_date;

public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException 
    logger.info("serialize:"+value);
    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    logger.info("DateSerializer formatter:"+formatter.format(value));
    jgen.writeString(formatter.format(value));

【问题讨论】:

【参考方案1】:
    如果要将JSON 字符串绑定到日期,则此过程称为deserialization,而不是serialization

    要将JSON 字符串绑定到日期,请创建自定义日期反序列化,注释created_date 或其设置器

    @JsonDeserialize(using=YourCustomDateDeserializer.class)

你必须在哪里实现 public Date deserialize(...) 方法来告诉 Jackson 如何将字符串转换为日期。

享受吧。

【讨论】:

【参考方案2】:

我有同样的问题,所以我写了一个自定义日期反序列化 @JsonDeserialize(using=CustomerDateAndTimeDeserialize.class)

public class CustomerDateAndTimeDeserialize extends JsonDeserializer<Date> 

    private SimpleDateFormat dateFormat = new SimpleDateFormat(
            "yyyy-MM-dd HH:mm:ss");

    @Override
    public Date deserialize(JsonParser paramJsonParser,
            DeserializationContext paramDeserializationContext)
            throws IOException, JsonProcessingException 
        String str = paramJsonParser.getText().trim();
        try 
            return dateFormat.parse(str);
         catch (ParseException e) 
            // Handle exception here
        
        return paramDeserializationContext.parseDate(str);
    

【讨论】:

你是如何实现这个 CustomerDateAndTimeDeserialize 类的?【参考方案3】:

使用JsonFormat 注释注释您的created_date 字段以指定输出格式。

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = TimeZone.getDefault(), locale = Locale.getDefault())

请注意,您可能需要传入不同的 Locale 和 TimeZone,如果它们应该基于服务器使用之外的其他内容。

您可以在the docs 中找到更多信息。

【讨论】:

您只需要这样做吗?我试过这个,它本身不起作用。也许某处需要其他一些注释? 你需要使用杰克逊:fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/… 注意使用这个注解。这是已知的issue,还有一天的时间。 如果你想要一个正确的时间,不要忘记在“模式”之后添加 timezone =“Canonical_ID_of_your_timezone”参数。时区名称可以在这里找到:joda-time.sourceforge.net/timezones.html 或者使用:@Pattern(regexp = Constants.REGEX)【参考方案4】:

另一种方法是使用一个自定义的 Date 对象来处理自己的序列化。

虽然我并不认为扩展像DateLong 等简单对象是一个好习惯,但在这种特殊情况下,它使代码易于阅读,在定义格式和与普通的Date 对象兼容。

public class CustomFormatDate extends Date 

    private DateFormat myDateFormat = ...; // your date format

    public CustomFormatDate() 
        super();
    

    public CustomFormatDate(long date) 
        super(date);
    

    public CustomFormatDate(Date date) 
        super(date.getTime());
    


    @JsonCreator
    public static CustomFormatDate forValue(String value) 
        try 
            return new CustomFormatDate(myDateFormat.parse(value));
         catch (ParseException e) 
            return null;
        
    

    @JsonValue
    public String toValue() 
        return myDateFormat.format(this);
    

    @Override
    public String toString() 
        return toValue();
    

【讨论】:

【参考方案5】:

我通过以下步骤解决了这个问题。

1.在实体类中使用@JsonDeserialize对其进行注释

@Entity
@Table(name="table")
public class Table implements Serializable 
// Some code
@JsonDeserialize(using= CustomerDateAndTimeDeserialize.class)
@Temporal(TemporalType.TIMESTAMP)
@Column(name="created_ts")
private Date createdTs

    写 CustomDateAndTimeDeserialize.java Sample Code

【讨论】:

【参考方案6】:

对于某人,如果您使用 DTO/VO/POJO 来映射您的请求,您可以简单地注释您的日期字段

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date customerRegDate;

而json请求应该是:


"someDate":"2020-04-04 16:11:02"

您不需要注释实体类变量。

【讨论】:

日期为空怎么办?【参考方案7】:

我需要使用@JsonFormat 进行注释,然后,这运行良好:

@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern = "MM-dd-yyyy")
@JsonFormat(pattern = "MM-dd-yyyy")
private java.util.Date expDate;

【讨论】:

以上是关于JSON 以自定义格式序列化日期(无法从字符串值构造 java.util.Date 的实例)的主要内容,如果未能解决你的问题,请参考以下文章

Ninja Framework 以自定义格式返回 JSON

如何以自定义 json 格式返回数据?

SpringBoot中使用@RequestBody时如何自定义需要转换的日期格式

字定义JSON序列化支持datetime格式序列化

使用非美国日期格式时,JsonConvert.DeserializeObject 无法将字符串转换为 DateTime

通过自己定义MVC的Controller的Json转换器解决日期序列化格式问题