add wast support

This commit is contained in:
Looly
2026-02-04 12:33:08 +08:00
parent 4a44155eb4
commit e93be8bf61
12 changed files with 231 additions and 18 deletions

View File

@@ -1,6 +1,6 @@
### 📣说明
1. 请确认你提交的PR是到'v6-dev'分支否则我会手动修改代码并关闭PR。
1. 请确认你提交的PR是到'v7-dev'分支否则我会手动修改代码并关闭PR。
2. 请确认没有更改代码风格如tab缩进
3. 新特性添加请确认注释完备如有必要请在src/test/java下添加Junit测试用例
@@ -12,8 +12,8 @@
### 😊提交前自测
> 请在提交前自测确保代码没有问题,提交新代码应包含:测试用例、通过(mvn javadoc:javadoc)检验详细注释。
1. 本地如有多个JDK版本可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home`具体替换为本地jdk目录
2. 确保本地测试使用JDK8最新版本,`echo $JAVA_HOME``mvn -v``java -version`均正确。
1. 本地如有多个JDK版本可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17/Contents/Home`具体替换为本地jdk目录
2. 确保本地测试使用JDK17最新版本,`echo $JAVA_HOME``mvn -v``java -version`均正确。
3. 执行打包生成文档,使用`mvn clean package -Dmaven.test.skip=true -U`,并确认通过,会自动执行打包、生成文档
4. 如需要单独执行文档生成,执行:`mvn javadoc:javadoc `,并确认通过
5. 如需要单独执行测试用例,执行:`mvn clean test`,并确认通过

View File

@@ -1,6 +1,6 @@
### 📣说明
1. 请确认你提交的PR是到'v5-dev'分支否则我会手动修改代码并关闭PR。
1. 请确认你提交的PR是到'v7-dev'分支否则我会手动修改代码并关闭PR。
2. 请确认没有更改代码风格如tab缩进
3. 新特性添加请确认注释完备如有必要请在src/test/java下添加Junit测试用例
@@ -12,8 +12,8 @@
### 😊提交前自测
> 请在提交前自测确保代码没有问题,提交新代码应包含:测试用例、通过(mvn javadoc:javadoc)检验详细注释。
1. 本地如有多个JDK版本可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home`具体替换为本地jdk目录
2. 确保本地测试使用JDK8最新版本,`echo $JAVA_HOME``mvn -v``java -version`均正确。
1. 本地如有多个JDK版本可以设置临时JDk版本,如:`export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17/Contents/Home`具体替换为本地jdk目录
2. 确保本地测试使用JDK17最新版本,`echo $JAVA_HOME``mvn -v``java -version`均正确。
3. 执行打包生成文档,使用`mvn clean package -Dmaven.test.skip=true -U`,并确认通过,会自动执行打包、生成文档
4. 如需要单独执行文档生成,执行:`mvn javadoc:javadoc `,并确认通过
5. 如需要单独执行测试用例,执行:`mvn clean test`,并确认通过

View File

@@ -5,7 +5,6 @@ sudo: false # faster builds
install: true
jdk:
- openjdk8
- openjdk17
notifications:

View File

@@ -42,6 +42,7 @@
<fastjson2.version>2.0.60</fastjson2.version>
<gson.version>2.13.2</gson.version>
<moshi.version>1.15.2</moshi.version>
<wast.version>0.0.29</wast.version>
</properties>
<dependencies>
@@ -97,5 +98,11 @@
<version>${moshi.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.wycst</groupId>
<artifactId>wast</artifactId>
<version>${wast.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -16,14 +16,15 @@
package cn.hutool.v7.jmh.json;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonElement;
import cn.hutool.v7.json.JSON;
import cn.hutool.v7.json.JSONUtil;
import cn.hutool.v7.json.engine.JSONEngine;
import cn.hutool.v7.json.engine.JSONEngineFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonElement;
import org.openjdk.jmh.annotations.*;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)//每次执行平均花费时间
@@ -39,6 +40,7 @@ public class FromJsonStringStrJmh {
private JSONEngine gsonEngine;
private JSONEngine fastJSONEngine;
private JSONEngine hutoolEngine;
private JSONEngine wastEngine;
private String jsonStr;
@@ -50,6 +52,7 @@ public class FromJsonStringStrJmh {
gsonEngine = JSONEngineFactory.createEngine("gson");
fastJSONEngine = JSONEngineFactory.createEngine("fastjson");
hutoolEngine = JSONEngineFactory.createEngine("hutool");
wastEngine = JSONEngineFactory.createEngine("wast");
}
@Benchmark
@@ -67,6 +70,11 @@ public class FromJsonStringStrJmh {
fastJSONEngine.fromJsonString(jsonStr, com.alibaba.fastjson2.JSON.class);
}
@Benchmark
public void wastJmh() {
wastEngine.fromJsonString(jsonStr, Map.class);
}
@Benchmark
public void hutoolJSONJmh() {
hutoolEngine.fromJsonString(jsonStr, JSON.class);

View File

@@ -27,6 +27,7 @@ import org.openjdk.jmh.annotations.*;
import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)//每次执行平均花费时间
@@ -42,6 +43,7 @@ public class deserializeJmh {
private JSONEngine gsonEngine;
private JSONEngine fastJSONEngine;
private JSONEngine hutoolEngine;
private JSONEngine wastEngine;
@Setup
public void setup() {
@@ -49,6 +51,7 @@ public class deserializeJmh {
gsonEngine = JSONEngineFactory.createEngine("gson");
fastJSONEngine = JSONEngineFactory.createEngine("fastjson");
hutoolEngine = JSONEngineFactory.createEngine("hutool");
wastEngine = JSONEngineFactory.createEngine("wast");
}
@Benchmark
@@ -78,6 +81,15 @@ public class deserializeJmh {
}
}
@Benchmark
public void wastJmh() {
try(final Reader jsonFileReader = FileUtil.getUtf8Reader(JSONJmhData.OUTPUT_FILE_PATH)){
wastEngine.deserialize(jsonFileReader, Map.class);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
@Benchmark
public void hutoolJSONJmh() {
try(final Reader jsonFileReader = FileUtil.getUtf8Reader(JSONJmhData.OUTPUT_FILE_PATH)){

View File

@@ -40,6 +40,7 @@
<fastjson2.version>2.0.60</fastjson2.version>
<gson.version>2.13.2</gson.version>
<moshi.version>1.15.2</moshi.version>
<wast.version>0.0.29</wast.version>
</properties>
<dependencies>
@@ -86,6 +87,12 @@
<version>${moshi.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.github.wycst</groupId>
<artifactId>wast</artifactId>
<version>${wast.version}</version>
<optional>true</optional>
</dependency>
<!-- 测试特殊算法 -->
<dependency>

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2026 Hutool Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hutool.v7.json.engine.wast;
import cn.hutool.v7.core.io.IoUtil;
import cn.hutool.v7.core.lang.Assert;
import cn.hutool.v7.core.text.StrUtil;
import cn.hutool.v7.core.util.ObjUtil;
import cn.hutool.v7.json.engine.AbstractJSONEngine;
import cn.hutool.v7.json.engine.JSONEngineConfig;
import io.github.wycst.wast.common.reflect.GenericParameterizedType;
import io.github.wycst.wast.json.JSON;
import io.github.wycst.wast.json.JSONConfig;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.reflect.Type;
/**
* Wast引擎实现
*
* @author Looly
* @since 7.0.0
*/
public class WastEngine extends AbstractJSONEngine {
private JSONConfig wastConfig;
/**
* 构造
*/
public WastEngine() {
// issue#IABWBL JDK8下在IDEA旗舰版加载Spring boot插件时启动应用不会检查字段类是否存在
// 此处构造时调用下这个类,以便触发类是否存在的检查
Assert.notNull(JSON.class);
}
@Override
public void serialize(final Object bean, final OutputStream out) {
initEngine();
JSON.writeJsonTo(bean, out, this.wastConfig);
}
@SuppressWarnings("unchecked")
@Override
public <T> T deserialize(final Reader reader, final Object type) {
initEngine();
https://github.com/wycst/wast/issues/3
// final JSONReader jsonReader = new JSONReader(reader);
// return (T) jsonReader.readAsResult(GenericParameterizedType.of((Type) type));
return (T) JSON.parse(IoUtil.read(reader), GenericParameterizedType.of((Type) type));
}
@SuppressWarnings("unchecked")
@Override
public <T> T fromJsonString(final String jsonStr, final Object type) {
initEngine();
return (T) JSON.parse(jsonStr, GenericParameterizedType.of((Type) type));
}
@Override
protected void reset() {
wastConfig = null;
}
@Override
protected void initEngine() {
if(null != this.wastConfig){
return;
}
this.config = ObjUtil.defaultIfNull(this.config, JSONEngineConfig::of);
final JSONEngineConfig config = ObjUtil.defaultIfNull(this.config, JSONEngineConfig::of);
this.wastConfig = JSONConfig.of();
this.wastConfig.setFormatOut(config.isPrettyPrint());
final String dateFormat = config.getDateFormat();
if(StrUtil.isNotBlank(dateFormat)){
this.wastConfig.setDateFormat(true);
this.wastConfig.setDateFormatPattern(dateFormat);
}
}
}

View File

@@ -19,3 +19,4 @@ cn.hutool.v7.json.engine.gson.GsonEngine
cn.hutool.v7.json.engine.fastjson.FastJSON2Engine
cn.hutool.v7.json.engine.moshi.MoshiEngine
cn.hutool.v7.json.engine.HutoolJSONEngine
cn.hutool.v7.json.engine.wast.WastEngine

View File

@@ -16,16 +16,17 @@
package cn.hutool.v7.json.engine;
import cn.hutool.v7.core.lang.Console;
import cn.hutool.v7.core.text.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import cn.hutool.v7.core.lang.Console;
import cn.hutool.v7.core.text.StrUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FastJSONTest {
@Test
void prettyPrintTest() {
@@ -36,7 +37,7 @@ public class FastJSONTest {
String jsonString = engine.toJsonString(testBean);
// 使用统一换行符
jsonString = StrUtil.removeAll(jsonString, '\r');
Assertions.assertEquals("""
assertEquals("""
{
"name":"张三",
"age":18,

View File

@@ -20,11 +20,12 @@ import cn.hutool.v7.core.collection.ListUtil;
import cn.hutool.v7.core.date.DateTime;
import cn.hutool.v7.core.date.DateUtil;
import cn.hutool.v7.core.date.TimeUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class GsonTest {
/**
* Gson默认缩进两个空格使用\n换行符
@@ -37,7 +38,7 @@ public class GsonTest {
final JSONEngineTest.TestBean testBean = new JSONEngineTest.TestBean("张三", 18, true);
final String jsonString = engine.toJsonString(testBean);
// 使用统一换行符
Assertions.assertEquals("""
assertEquals("""
{
"name": "张三",
"age": 18,
@@ -52,10 +53,10 @@ public class GsonTest {
final JSONEngine engine = JSONEngineFactory.createEngine("gson");
final String jsonString = engine.toJsonString(bean);
Assertions.assertEquals("{\"date\":1704038400000}", jsonString);
assertEquals("{\"date\":1704038400000}", jsonString);
engine.init(JSONEngineConfig.of().setDateFormat("yyyy-MM-dd HH:mm:ss"));
Assertions.assertEquals("{\"date\":\"2024-01-01 00:00:00\"}", engine.toJsonString(bean));
assertEquals("{\"date\":\"2024-01-01 00:00:00\"}", engine.toJsonString(bean));
}
@Test
@@ -63,6 +64,6 @@ public class GsonTest {
final ArrayList<Integer> integers = ListUtil.of(1, 2, 3);
final JSONEngine engine = JSONEngineFactory.createEngine("gson");
final String jsonString = engine.toJsonString(integers);
Assertions.assertEquals("[1,2,3]", jsonString);
assertEquals("[1,2,3]", jsonString);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2013-2026 Hutool Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hutool.v7.json.engine;
import cn.hutool.v7.core.text.StrUtil;
import org.junit.jupiter.api.Test;
import java.io.StringReader;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class WastTest {
final String jsonStr = """
{
"name": "张三",
"age": 18,
"birthday": "2020-01-01",
"booleanValue": true,
"jsonObjectSub": {
"subStr": "abc",
"subNumber": 150343445454,
"subBoolean": true
},
"jsonArraySub": [
"abc",
123,
false
]
}""";
@Test
void prettyPrintTest() {
final JSONEngine engine = JSONEngineFactory.createEngine("wast");
engine.init(JSONEngineConfig.of().setPrettyPrint(true));
final JSONEngineTest.TestBean testBean = new JSONEngineTest.TestBean("张三", 18, true);
String jsonString = engine.toJsonString(testBean);
// 使用统一换行符
jsonString = StrUtil.removeAll(jsonString, '\r');
assertEquals("""
{
"age":18,
"gender":true,
"name":"张三"
}""", jsonString);
}
@Test
void fromJsonStringTest() {
final JSONEngine engine = JSONEngineFactory.createEngine("wast");
final Map<String, Object> resultMap = engine.fromJsonString(jsonStr, Map.class);
assertNotNull(resultMap);
assertEquals(6, resultMap.size());
}
@Test
void deserializeTest() {
final JSONEngine engine = JSONEngineFactory.createEngine("wast");
final Map<String, Object> resultMap = engine.deserialize(new StringReader(jsonStr), Map.class);
assertNotNull(resultMap);
assertEquals(6, resultMap.size());
}
}