This commit is contained in:
Looly 2022-09-30 21:45:32 +08:00
parent e7be2fed6b
commit 5f61405464
4 changed files with 65 additions and 57 deletions

View File

@ -91,6 +91,7 @@ public final class InternalJSONUtil {
|| object instanceof Calendar
|| object instanceof TemporalAccessor
) {
// 日期类型保存原始类型用于在writer时自定义转字符串
return object;
}
// 枚举类保存其字符串形式4.0.2新增

View File

@ -1,6 +1,8 @@
package cn.hutool.json.serialize;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.convert.Converter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.date.format.GlobalCustomFormat;
@ -8,6 +10,8 @@ import cn.hutool.core.text.StrUtil;
import cn.hutool.json.InternalJSONUtil;
import cn.hutool.json.JSONConfig;
import java.lang.reflect.Type;
import java.time.MonthDay;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
@ -19,28 +23,55 @@ import java.util.Date;
* @author looly
* @since 6.0.0
*/
public class DateJSONString implements JSONString {
public class DateJSONString implements JSONString, Converter {
final Object dateObj;
final JSONConfig jsonConfig;
/**
* 构造
*
* @param dateObj 日期对象支持包括DateCalendarTemporalAccessor
* @param jsonConfig JSON配置
*/
public DateJSONString(final Object dateObj, final JSONConfig jsonConfig) {
this.dateObj = dateObj;
this.jsonConfig = jsonConfig;
}
/**
* 获取原始的日期对象{@link Date}{@link Calendar}{@link TemporalAccessor}
*
* @return 日期对象
*/
public Object getDateObj() {
return this.dateObj;
}
@Override
public String toJSONString() {
return formatDate(this.jsonConfig.getDateFormat());
// issue#2572@Github
if (dateObj instanceof MonthDay) {
return InternalJSONUtil.quote(dateObj.toString());
}
return formatDate(this.dateObj, this.jsonConfig.getDateFormat());
}
@Override
public Object convert(Type targetType, Object value) throws ConvertException {
return Convert.convert(targetType, this.dateObj);
}
/**
* 按照给定格式格式化日期格式为空时返回时间戳字符串
* 按照给定格式格式化日期格式为空时返回时间戳字符串<br>
* 如果给定的格式是时间戳直接返回时间戳字符串如果是给定字符串格式返回带双引号包装的字符串
*
* @param format 格式
* @param dateObj Date或者Calendar对象
* @param format 格式
* @return 日期字符串
*/
private String formatDate(final String format) {
private static String formatDate(final Object dateObj, final String format) {
if (StrUtil.isNotBlank(format)) {
final String dateStr;
if (dateObj instanceof TemporalAccessor) {

View File

@ -1,9 +1,5 @@
package cn.hutool.json.serialize;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
import cn.hutool.core.date.format.GlobalCustomFormat;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.math.NumberUtil;
@ -16,7 +12,6 @@ import cn.hutool.json.JSONException;
import java.io.IOException;
import java.io.Writer;
import java.time.MonthDay;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
@ -236,15 +231,8 @@ public class JSONWriter extends Writer {
} else if (value instanceof Number) {
writeNumberValue((Number) value);
} else if (value instanceof Date || value instanceof Calendar || value instanceof TemporalAccessor) {
// issue#2572@Github
if(value instanceof MonthDay){
writeQuoteStrValue(value.toString());
return this;
}
final String format = (null == config) ? null : config.getDateFormat();
//noinspection resource
writeRaw(formatDate(value, format));
writeRaw(new DateJSONString(value, config).toJSONString());
} else if (value instanceof Boolean) {
writeBooleanValue((Boolean) value);
} else if (value instanceof JSONString) {
@ -370,43 +358,4 @@ public class JSONWriter extends Writer {
}
return this;
}
/**
* 按照给定格式格式化日期格式为空时返回时间戳字符串
*
* @param dateObj Date或者Calendar对象
* @param format 格式
* @return 日期字符串
*/
private static String formatDate(final Object dateObj, final String format) {
if (StrUtil.isNotBlank(format)) {
final String dateStr;
if (dateObj instanceof TemporalAccessor) {
dateStr = TemporalAccessorUtil.format((TemporalAccessor) dateObj, format);
} else {
dateStr = DateUtil.format(Convert.toDate(dateObj), format);
}
if (GlobalCustomFormat.FORMAT_SECONDS.equals(format)
|| GlobalCustomFormat.FORMAT_MILLISECONDS.equals(format)) {
// Hutool自定义的秒和毫秒表示默认不包装双引号
return dateStr;
}
//用户定义了日期格式
return InternalJSONUtil.quote(dateStr);
}
//默认使用时间戳
final long timeMillis;
if (dateObj instanceof TemporalAccessor) {
timeMillis = TemporalAccessorUtil.toEpochMilli((TemporalAccessor) dateObj);
} else if (dateObj instanceof Date) {
timeMillis = ((Date) dateObj).getTime();
} else if (dateObj instanceof Calendar) {
timeMillis = ((Calendar) dateObj).getTimeInMillis();
} else {
throw new UnsupportedOperationException("Unsupported Date type: " + dateObj.getClass());
}
return String.valueOf(timeMillis);
}
}

View File

@ -0,0 +1,27 @@
package cn.hutool.json;
import cn.hutool.core.date.DateUtil;
import org.junit.Assert;
import org.junit.Test;
import java.util.Date;
public class JSONWriterTest {
@Test
public void writeDateTest() {
final JSONObject jsonObject = JSONUtil.ofObj(JSONConfig.of().setDateFormat("yyyy-MM-dd"))
.set("date", DateUtil.parse("2022-09-30"));
// 日期原样写入
final Date date = jsonObject.getDate("date");
Assert.assertEquals("2022-09-30 00:00:00", date.toString());
// 自定义日期格式生效
Assert.assertEquals("{\"date\":\"2022-09-30\"}", jsonObject.toString());
// 自定义日期格式解析生效
final JSONObject parse = JSONUtil.parseObj(jsonObject.toString(), JSONConfig.of().setDateFormat("yyyy-MM-dd"));
Assert.assertEquals(String.class, parse.get("date").getClass());
}
}