add config

This commit is contained in:
Looly
2024-09-05 01:40:31 +08:00
parent 0d0237488e
commit 979bbe2905
12 changed files with 208 additions and 13 deletions

View File

@@ -33,6 +33,7 @@
<!-- versions -->
<bouncycastle.version>1.78.1</bouncycastle.version>
<jjwt.version>0.12.6</jjwt.version>
<jackson.version>2.17.2</jackson.version>
</properties>
<dependencies>
@@ -52,9 +53,15 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>

View File

@@ -94,6 +94,8 @@ public class FastJSON2Engine extends AbstractJSONEngine {
protected void initEngine() {
if(null == this.readerContext){
this.readerContext = JSONFactory.createReadContext();
final String dateFormat = ObjUtil.defaultIfNull(this.config, JSONEngineConfig::getDateFormat, "millis");
this.readerContext.setDateFormat(ObjUtil.defaultIfNull(dateFormat, "millis"));
}
if(null == this.writerContext){
final List<JSONWriter.Feature> features = ListUtil.of();
@@ -101,6 +103,10 @@ public class FastJSON2Engine extends AbstractJSONEngine {
features.add(JSONWriter.Feature.PrettyFormat);
}
this.writerContext = JSONFactory.createWriteContext(features.toArray(new JSONWriter.Feature[0]));
// 自定义配置
final String dateFormat = ObjUtil.defaultIfNull(this.config, JSONEngineConfig::getDateFormat, "millis");
this.writerContext.setDateFormat(ObjUtil.defaultIfNull(dateFormat, "millis"));
}
}
}

View File

@@ -16,15 +16,18 @@
package org.dromara.hutool.json.engine;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.*;
import org.dromara.hutool.core.date.TimeUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.JSONException;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.Date;
/**
* Gson引擎实现
@@ -32,7 +35,7 @@ import java.lang.reflect.Type;
* @author Looly
* @since 6.0.0
*/
public class GsonEngine extends AbstractJSONEngine{
public class GsonEngine extends AbstractJSONEngine {
private Gson gson;
@@ -55,10 +58,10 @@ public class GsonEngine extends AbstractJSONEngine{
@Override
public <T> T deserialize(final Reader reader, final Object type) {
initEngine();
if(type instanceof Class){
return gson.fromJson(reader, (Class<T>)type);
} else if(type instanceof Type){
return gson.fromJson(reader, (Type)type);
if (type instanceof Class) {
return gson.fromJson(reader, (Class<T>) type);
} else if (type instanceof Type) {
return gson.fromJson(reader, (Type) type);
}
throw new JSONException("Unsupported type: {}", type.getClass());
@@ -71,14 +74,28 @@ public class GsonEngine extends AbstractJSONEngine{
@Override
protected void initEngine() {
if(null != this.gson){
if (null != this.gson) {
return;
}
final GsonBuilder builder = new GsonBuilder();
if(ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false)){
if (ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false)) {
builder.setPrettyPrinting();
}
final String dateFormat = ObjUtil.apply(this.config, JSONEngineConfig::getDateFormat);
if (StrUtil.isNotEmpty(dateFormat)) {
builder.setDateFormat(dateFormat);
builder.registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, typeOfT, context) -> TimeUtil.parse(json.getAsString(), dateFormat));
builder.registerTypeAdapter(LocalDateTime.class, (JsonSerializer<LocalDateTime>) (date, type, jsonSerializationContext) -> new JsonPrimitive(TimeUtil.format(date, dateFormat)));
} else {
// 无自定义格式,则默认输出时间戳
// https://stackoverflow.com/questions/41979086/how-to-serialize-date-to-long-using-gson
builder.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> new Date(json.getAsJsonPrimitive().getAsLong()));
builder.registerTypeAdapter(Date.class, (JsonSerializer<Date>) (date, type, jsonSerializationContext) -> new JsonPrimitive(date.getTime()));
builder.registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, typeOfT, context) -> TimeUtil.of(json.getAsJsonPrimitive().getAsLong()));
builder.registerTypeAdapter(LocalDateTime.class, (JsonSerializer<LocalDateTime>) (date, type, jsonSerializationContext) -> new JsonPrimitive(TimeUtil.toEpochMilli(date)));
}
this.gson = builder.create();
}
}

View File

@@ -60,6 +60,12 @@ public class HutoolJSONEngine extends AbstractJSONEngine {
return;
}
hutoolSJONConfig = JSONConfig.of();
// 自定义配置
final JSONConfig hutoolSJONConfig = JSONConfig.of();
if(null != this.config){
hutoolSJONConfig.setDateFormat(this.config.getDateFormat());
}
this.hutoolSJONConfig = hutoolSJONConfig;
}
}

View File

@@ -40,6 +40,10 @@ public class JSONEngineConfig implements Serializable {
* 是否格式化输出
*/
private boolean prettyPrint;
/**
* 日期格式null表示默认的时间戳
*/
private String dateFormat;
/**
* 获取是否启用格式化输出
@@ -60,4 +64,25 @@ public class JSONEngineConfig implements Serializable {
this.prettyPrint = prettyPrint;
return this;
}
/**
* 日期格式null表示默认的时间戳
*
* @return 日期格式null表示默认的时间戳
*/
public String getDateFormat() {
return dateFormat;
}
/**
* 设置日期格式null表示默认的时间戳<br>
* 此方法设置的日期格式仅对转换为JSON字符串有效对解析JSON为bean无效。
*
* @param dateFormat 日期格式null表示默认的时间戳
* @return this
*/
public JSONEngineConfig setDateFormat(final String dateFormat) {
this.dateFormat = dateFormat;
return this;
}
}

View File

@@ -51,6 +51,9 @@ public class JSONEngineFactory {
if(StrUtil.equalsIgnoreCase("fastjson", engineName)){
engineName = "FastJSON2";
}
if(StrUtil.equalsIgnoreCase("hutool", engineName)){
engineName = "HutoolJSON";
}
if (!StrUtil.endWithIgnoreCase(engineName, "Engine")) {
engineName = engineName + "Engine";

View File

@@ -19,10 +19,14 @@ package org.dromara.hutool.json.engine;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.reflect.ConstructorUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.JSONException;
@@ -48,6 +52,16 @@ public class JacksonEngine extends AbstractJSONEngine {
Assert.notNull(ObjectMapper.class);
}
/**
* 获取Jackson的{@link ObjectMapper}对象
*
* @return {@link ObjectMapper}对象
*/
public ObjectMapper getMapper() {
initEngine();
return mapper;
}
@Override
public void serialize(final Object bean, final Writer writer) {
initEngine();
@@ -84,7 +98,7 @@ public class JacksonEngine extends AbstractJSONEngine {
@Override
protected void initEngine() {
if(null != this.mapper){
if (null != this.mapper) {
return;
}
@@ -99,10 +113,36 @@ public class JacksonEngine extends AbstractJSONEngine {
);
// 自定义配置
if(ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false)){
if (ObjUtil.defaultIfNull(this.config, JSONEngineConfig::isPrettyPrint, false)) {
mapper.enable(SerializationFeature.INDENT_OUTPUT);
}
final String dateFormat = ObjUtil.apply(this.config, JSONEngineConfig::getDateFormat);
if(StrUtil.isNotEmpty(dateFormat)){
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.setDateFormat(DateUtil.newSimpleFormat(dateFormat));
}
// 支持Java8+日期格式
registerModule(mapper, "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule");
this.mapper = mapper;
}
/**
* 注册模块
*
* @param mapper Jackson的{@link ObjectMapper}对象
* @param moduleClass 模块类名
*/
@SuppressWarnings("SameParameterValue")
private void registerModule(final ObjectMapper mapper, final String moduleClass) {
final Class<?> aClass;
try {
aClass = Class.forName(moduleClass);
} catch (final ClassNotFoundException ignore) {
//用户未引入JSR310则跳过不加载模块
return;
}
mapper.registerModule((Module) ConstructorUtil.newInstance(aClass));
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2024. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.json.engine;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@AllArgsConstructor
public class BeanWithDate {
private Date date1;
private LocalDateTime date2;
}

View File

@@ -1,5 +1,8 @@
package org.dromara.hutool.json.engine;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -20,4 +23,17 @@ public class FastJSONTest {
" \"gender\":true\n" +
"}", jsonString);
}
@Test
void writeDateFormatTest() {
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
final JSONEngine engine = JSONEngineFactory.createEngine("fastjson");
final String jsonString = engine.toJsonString(bean);
Assertions.assertEquals("{\"date1\":1704042741000,\"date2\":1704042741000}", jsonString);
engine.init(JSONEngineConfig.of().setDateFormat("yyyy-MM-dd HH:mm:ss"));
Assertions.assertEquals("{\"date1\":\"2024-01-01 01:12:21\",\"date2\":\"2024-01-01 01:12:21\"}", engine.toJsonString(bean));
}
}

View File

@@ -1,5 +1,8 @@
package org.dromara.hutool.json.engine;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -21,4 +24,17 @@ public class GsonTest {
" \"gender\": true\n" +
"}", jsonString);
}
@Test
void writeDateFormatTest() {
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
final JSONEngine engine = JSONEngineFactory.createEngine("gson");
final String jsonString = engine.toJsonString(bean);
Assertions.assertEquals("{\"date1\":1704042741000,\"date2\":1704042741000}", jsonString);
engine.init(JSONEngineConfig.of().setDateFormat("yyyy-MM-dd HH:mm:ss"));
Assertions.assertEquals("{\"date1\":\"2024-01-01 01:12:21\",\"date2\":\"2024-01-01 01:12:21\"}", engine.toJsonString(bean));
}
}

View File

@@ -1,5 +1,8 @@
package org.dromara.hutool.json.engine;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -17,4 +20,17 @@ public class HutoolJSONTest {
" \"gender\": true\n" +
"}", jsonString);
}
@Test
void writeDateFormatTest() {
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
final JSONEngine engine = JSONEngineFactory.createEngine("hutool");
final String jsonString = engine.toJsonString(bean);
Assertions.assertEquals("{\"date1\":1704042741000,\"date2\":1704042741000}", jsonString);
engine.init(JSONEngineConfig.of().setDateFormat("yyyy-MM-dd HH:mm:ss"));
Assertions.assertEquals("{\"date1\":\"2024-01-01 01:12:21\",\"date2\":\"2024-01-01 01:12:21\"}", engine.toJsonString(bean));
}
}

View File

@@ -1,5 +1,8 @@
package org.dromara.hutool.json.engine;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -23,4 +26,18 @@ public class JacksonTest {
" \"gender\" : true\n" +
"}", jsonString);
}
@Test
void writeDateFormatTest() {
final DateTime date = DateUtil.parse("2024-01-01 01:12:21");
final BeanWithDate bean = new BeanWithDate(date, TimeUtil.of(date));
final JSONEngine engine = JSONEngineFactory.createEngine("jackson");
final String jsonString = engine.toJsonString(bean);
Assertions.assertEquals("{\"date1\":1704042741000,\"date2\":[2024,1,1,1,12,21]}", jsonString);
//TODO LocalDateTime的格式化未解决
engine.init(JSONEngineConfig.of().setDateFormat("yyyy-MM-dd HH:mm:ss"));
Assertions.assertEquals("{\"date1\":\"2024-01-01 01:12:21\",\"date2\":\"2024-01-01T01:12:21\"}", engine.toJsonString(bean));
}
}