通过 FastJsonConfig 设置 DateFormat 时,不论设置什么值,只要属性类型为 LocalDateTime ,返回的都是 yyyy-MM-dd HH:mm:ss 格式

djmepvbi  于 4个月前  发布在  其他
关注(0)|答案(3)|浏览(45)

fastjson测试版本:1.2.76
jdk版本:OracleJDK 16.0.1
测试代码:

class LocalDateTimeTest {

	@Data
	private class TestModel {
		private LocalDateTime createTime;
	}

	@Test
	void test() throws Exception {
		TestModel model = new TestModel();
		model.setCreateTime(LocalDateTime.now());

		FastJsonConfig config = new FastJsonConfig();
		
		config.setDateFormat("不论填写什么值都一样,哪怕就是这几个汉字");

		FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
		converter.setFastJsonConfig(config);

		converter.canRead(TestModel.class, MediaType.APPLICATION_JSON_UTF8);
		converter.canWrite(TestModel.class, MediaType.APPLICATION_JSON_UTF8);

		final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
		HttpOutputMessage out = new HttpOutputMessage() {
			public HttpHeaders getHeaders() {
				return new HttpHeaders() {
					private static final long serialVersionUID = 1L;

					@Override
					public MediaType getContentType() {
						return MediaType.APPLICATION_JSON;
					}
				};
			}

			public OutputStream getBody() throws IOException {
				return byteOut;
			}
		};

		converter.write(model, TestModel.class, MediaType.APPLICATION_JSON_UTF8, out);

		byte[] bytes = byteOut.toByteArray();
		String jsonString = new String(bytes, "UTF-8");

		System.out.println(jsonString);
	}
}

输出结果:

{"createTime":"2021-06-13 16:08:20"}
r1zhe5dt

r1zhe5dt1#

这里个人感觉是当前fastJson版本的一个缺陷,对应LocalDateTime类型的处理器Jdk8DateCodec,当前并没有支持自定义日期格式,相关代码为:
//Jdk8DateCodec 539行附近

if (format == null) { if ((features & mask) != 0 || serializer.isEnabled(SerializerFeature.UseISO8601DateFormat)) { format = formatter_iso8601_pattern; } else if (serializer.isEnabled(SerializerFeature.WriteDateUseDateFormat)) { format = JSON.DEFFAULT_DATE_FORMAT; //当前是走的这个分支,但是这里用默认格式而非识别你传递的类型 } else { int nano = dateTime.getNano(); if (nano == 0) { format = formatter_iso8601_pattern; } else if (nano % 1000000 == 0) { format = formatter_iso8601_pattern_23; } else { format = formatter_iso8601_pattern_29; } } }

解决方式:
1.如果你需要的格式恰好是上面代码里已支持的其他几个格式,可以考虑通过条件控制让代码走对应需要的分支(取巧)

2.如果一定需要自定义格式,可以考虑传递的过程用老的Date类型,Date类型能支持自定义格式(规避这个问题)

其他:
我后面尝试提交一个pr来修复一下这个问题,不过不太确定会否被采纳

14ifxucb

14ifxucb2#

这里个人感觉是当前fastJson版本的一个缺陷,对应LocalDateTime类型的处理器Jdk8DateCodec,当前并没有支持自定义日期格式,相关代码为:
//Jdk8DateCodec 539行附近

if (format == null) { if ((features & mask) != 0 || serializer.isEnabled(SerializerFeature.UseISO8601DateFormat)) { format = formatter_iso8601_pattern; } else if (serializer.isEnabled(SerializerFeature.WriteDateUseDateFormat)) { format = JSON.DEFFAULT_DATE_FORMAT; //当前是走的这个分支,但是这里用默认格式而非识别你传递的类型 } else { int nano = dateTime.getNano(); if (nano == 0) { format = formatter_iso8601_pattern; } else if (nano % 1000000 == 0) { format = formatter_iso8601_pattern_23; } else { format = formatter_iso8601_pattern_29; } } }

解决方式:
1.如果你需要的格式恰好是上面代码里已支持的其他几个格式,可以考虑通过条件控制让代码走对应需要的分支(取巧)

2.如果一定需要自定义格式,可以考虑传递的过程用老的Date类型,Date类型能支持自定义格式(规避这个问题)

其他:
我后面尝试提交一个pr来修复一下这个问题,不过不太确定会否被采纳

多谢你的回复,我主要是提个issue,希望能够有个官方的解决方案,我目前是使用暴力解决,部分代码如下

// LocalDateTime 转时间戳
config.getSerializeConfig().put(LocalDateTime.class, (serializer, object, fieldName, fieldType, features) -> {
	if (object == null) {
		serializer.out.writeNull();
		return;
	}
	serializer.out.writeLong(((LocalDateTime) object).atZone(JSON.defaultTimeZone.toZoneId()).toInstant().toEpochMilli());
});
rxztt3cl

rxztt3cl3#

这里个人感觉是当前fastJson版本的一个缺陷,对应LocalDateTime类型的处理器Jdk8DateCodec,当前并没有支持自定义日期格式,相关代码为:
//Jdk8DateCodec 539行附近
if (format == null) { if ((features & mask) != 0 || serializer.isEnabled(SerializerFeature.UseISO8601DateFormat)) { format = formatter_iso8601_pattern; } else if (serializer.isEnabled(SerializerFeature.WriteDateUseDateFormat)) { format = JSON.DEFFAULT_DATE_FORMAT; //当前是走的这个分支,但是这里用默认格式而非识别你传递的类型 } else { int nano = dateTime.getNano(); if (nano == 0) { format = formatter_iso8601_pattern; } else if (nano % 1000000 == 0) { format = formatter_iso8601_pattern_23; } else { format = formatter_iso8601_pattern_29; } } }
解决方式:
1.如果你需要的格式恰好是上面代码里已支持的其他几个格式,可以考虑通过条件控制让代码走对应需要的分支(取巧)
2.如果一定需要自定义格式,可以考虑传递的过程用老的Date类型,Date类型能支持自定义格式(规避这个问题)
其他:
我后面尝试提交一个pr来修复一下这个问题,不过不太确定会否被采纳

多谢你的回复,我主要是提个issue,希望能够有个官方的解决方案,我目前是使用暴力解决,部分代码如下

// LocalDateTime 转时间戳
config.getSerializeConfig().put(LocalDateTime.class, (serializer, object, fieldName, fieldType, features) -> {
	if (object == null) {
		serializer.out.writeNull();
		return;
	}
	serializer.out.writeLong(((LocalDateTime) object).atZone(JSON.defaultTimeZone.toZoneId()).toInstant().toEpochMilli());
});

棒~,这种写法应该就相当于自定义类型的解析器~,这样对LocalDateTime解析时走你自定义的这个而不是现在不支持自定义的Jdk8DateCodec这个了~ (我之前还以为对于fastJson里定制处理的类型解析不能用这种自定义的写法覆盖,原来我之前理解错了~ 囧)

相关问题