This is an automated email from the ASF dual-hosted git repository.
jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new 0df51ccfa2 feature: add fastjson2 jackson3 (#8046)
0df51ccfa2 is described below
commit 0df51ccfa254bb4cf6e50e1c484a2587e777f6a2
Author: legendpei <[email protected]>
AuthorDate: Wed Apr 15 11:28:58 2026 +0800
feature: add fastjson2 jackson3 (#8046)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 1 +
.../java/org/apache/seata/common/Constants.java | 10 ++
compatible/pom.xml | 2 +-
dependencies/pom.xml | 26 ++--
integration-tx-api/pom.xml | 2 +-
.../seata/integration/tx/api/json/JsonParser.java | 2 +-
.../integration/tx/api/json/JsonParserFactory.java | 2 +-
.../integration/tx/api/json/JsonParserWrap.java | 2 +-
.../seata/integration/tx/api/util/JsonUtil.java | 2 +-
json-common/{ => json-common-core}/pom.xml | 17 ++-
.../seata/common/json/JsonAllowlistManager.java | 0
.../apache/seata/common/json/JsonSerializer.java | 0
.../seata/common/json/JsonSerializerFactory.java | 21 ++-
.../org/apache/seata/common/json/JsonUtil.java | 0
.../common/json/impl/Fastjson2JsonSerializer.java} | 115 ++++++++--------
.../common/json/impl/FastjsonJsonSerializer.java | 7 +-
.../seata/common/json/impl/GsonJsonSerializer.java | 2 +-
.../common/json/impl/JacksonJsonSerializer.java | 7 +-
.../org.apache.seata.common.json.JsonSerializer | 1 +
.../seata/common/json/Fastjson2AllowlistTest.java} | 15 +--
.../common/json/Fastjson2JsonSerializerTest.java} | 126 ++++++++++++------
.../seata/common/json/FastjsonAllowlistTest.java | 0
.../common/json/FastjsonJsonSerializerTest.java | 34 +++++
.../seata/common/json/GsonJsonSerializerTest.java | 27 ++++
.../seata/common/json/JacksonAllowlistTest.java | 0
.../common/json/JacksonJsonSerializerTest.java | 38 ++++++
.../common/json/JsonAllowlistManagerTest.java | 0
.../common/json/JsonSerializerFactoryTest.java | 145 +++++++++++++++++++++
.../org/apache/seata/common/json/JsonUtilTest.java | 0
.../src/test/resources/file.conf | 0
.../src/test/resources/registry.conf | 0
.../json-common-jackson3}/pom.xml | 31 +++--
.../common/json/impl/Jackson3JsonSerializer.java} | 121 +++++++----------
.../org.apache.seata.common.json.JsonSerializer | 4 +-
.../seata/common/json/Jackson3AllowlistTest.java} | 22 ++--
.../common/json/Jackson3JsonSerializerTest.java} | 136 ++++++++++---------
json-common/pom.xml | 55 +++-----
rm-datasource/pom.xml | 2 +-
.../org.apache.seata.common.json.JsonSerializer | 1 +
.../org.apache.seata.common.json.JsonSerializer | 1 +
saga/pom.xml | 2 +-
.../seata/saga/statelang/parser/JsonParser.java | 2 +-
.../saga/statelang/parser/JsonParserFactory.java | 2 +-
.../saga/statelang/parser/impl/FastjsonParser.java | 2 +-
.../statelang/parser/impl/JacksonJsonParser.java | 2 +-
.../org.apache.seata.common.json.JsonSerializer | 1 +
script/client/spring/application.properties | 2 +-
script/client/spring/application.yml | 2 +-
script/config-center/config.txt | 2 +-
.../seata-spring-autoconfigure-client/pom.xml | 2 +-
.../additional-spring-configuration-metadata.json | 12 ++
.../apache/seata/rm/tcc/json/FastJsonParser.java | 2 +-
.../apache/seata/rm/tcc/json/GsonJsonParser.java | 2 +-
.../seata/rm/tcc/json/JacksonJsonParser.java | 2 +-
55 files changed, 666 insertions(+), 349 deletions(-)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 12bd27dbc6..6b09014774 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -29,6 +29,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#8002](https://github.com/apache/incubator-seata/pull/8002)] add Grafana
dashboard JSON for NamingServer metrics
- [[#8020](https://github.com/apache/incubator-seata/pull/8020)] add
UnregisterRM protocol to notify server on client destroy
- [[#8044](https://github.com/apache/incubator-seata/pull/8044)] add protobuf
serialization support for UnregisterRM protocol
+- [[#8046](https://github.com/apache/incubator-seata/pull/8046)] add fastjson2
and jackson3
### bugfix:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index b410d3de8c..4f3a8bf2d8 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -30,6 +30,7 @@
- [[#8002](https://github.com/apache/incubator-seata/pull/8002)]
为namingserver指标增加Grafana dashboard JSON
- [[#8020](https://github.com/apache/incubator-seata/pull/8020)] 新增
UnregisterRM 协议,在客户端销毁时通知服务端
- [[#8044](https://github.com/apache/incubator-seata/pull/8044)] 为
UnregisterRM 协议添加 protobuf 序列化支持
+- [[#8046](https://github.com/apache/incubator-seata/pull/8046)] 添加了 fastjson2
和 jackson3
### bugfix:
diff --git a/common/src/main/java/org/apache/seata/common/Constants.java
b/common/src/main/java/org/apache/seata/common/Constants.java
index c386992d03..c10416c1cb 100644
--- a/common/src/main/java/org/apache/seata/common/Constants.java
+++ b/common/src/main/java/org/apache/seata/common/Constants.java
@@ -219,6 +219,16 @@ public interface Constants {
*/
String JACKSON_JSON_PARSER_NAME = "jackson";
+ /**
+ * The constant FASTJSON2_JSON_PARSER_NAME
+ */
+ String FASTJSON2_JSON_PARSER_NAME = "fastjson2";
+
+ /**
+ * The constant JACKSON3_JSON_PARSER_NAME
+ */
+ String JACKSON3_JSON_PARSER_NAME = "jackson3";
+
/**
* The constant GSON_JSON_PARSER_NAME
*/
diff --git a/compatible/pom.xml b/compatible/pom.xml
index 09ffaaba1c..2ceb1ab96a 100644
--- a/compatible/pom.xml
+++ b/compatible/pom.xml
@@ -42,7 +42,7 @@
</dependency>
<dependency>
<groupId>org.apache.seata</groupId>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index ff06e6bff3..5fc0214463 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -87,6 +87,7 @@
<groovy.version>2.4.4</groovy.version>
<zstd.version>1.5.0-4</zstd.version>
<jackson.version>2.18.3</jackson.version>
+ <jackson3.version>3.1.1</jackson3.version>
<xstream.version>1.4.21</xstream.version>
<checker-qual.version>3.37.0</checker-qual.version>
<error_prone_annotations.version>2.21.1</error_prone_annotations.version>
@@ -151,6 +152,23 @@
<dependencyManagement>
<dependencies>
+ <!-- Jackson 3.x -->
+ <dependency>
+ <groupId>tools.jackson</groupId>
+ <artifactId>jackson-bom</artifactId>
+ <version>${jackson3.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <!-- Jackson 2.x BOM -->
+ <dependency>
+ <groupId>com.fasterxml.jackson</groupId>
+ <artifactId>jackson-bom</artifactId>
+ <version>${jackson.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
<!-- junit5 -->
<dependency>
<groupId>org.junit</groupId>
@@ -913,14 +931,6 @@
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
- <!-- Jackson BOM to manage all Jackson dependencies -->
- <dependency>
- <groupId>com.fasterxml.jackson</groupId>
- <artifactId>jackson-bom</artifactId>
- <version>${jackson.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
diff --git a/integration-tx-api/pom.xml b/integration-tx-api/pom.xml
index 39895c2d0a..f5e67b49e5 100644
--- a/integration-tx-api/pom.xml
+++ b/integration-tx-api/pom.xml
@@ -59,7 +59,7 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
index bd5475924a..6fe82c5e01 100644
---
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
+++
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
@@ -19,7 +19,7 @@ package org.apache.seata.integration.tx.api.json;
import java.io.IOException;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common-core module instead.
*/
@Deprecated
public interface JsonParser {
diff --git
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
index 0665d978e9..c5b38833a5 100644
---
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
+++
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
@@ -25,7 +25,7 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory}
in json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory}
in json-common-core module instead.
*/
@Deprecated
public class JsonParserFactory {
diff --git
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
index e0f0343d4e..a09b605400 100644
---
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
+++
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
@@ -19,7 +19,7 @@ package org.apache.seata.integration.tx.api.json;
import org.apache.seata.common.exception.JsonParseException;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common-core module instead.
*/
@Deprecated
public class JsonParserWrap implements JsonParser {
diff --git
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
index 037f68a602..23601b2a1b 100644
---
a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
+++
b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
@@ -25,7 +25,7 @@ import
org.apache.seata.integration.tx.api.json.JsonParserFactory;
import java.util.Objects;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonUtil} in
json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonUtil} in
json-common-core module instead.
*/
@Deprecated
public class JsonUtil {
diff --git a/json-common/pom.xml b/json-common/json-common-core/pom.xml
similarity index 84%
copy from json-common/pom.xml
copy to json-common/json-common-core/pom.xml
index a1588df199..9c69f312cd 100644
--- a/json-common/pom.xml
+++ b/json-common/json-common-core/pom.xml
@@ -22,14 +22,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.seata</groupId>
- <artifactId>seata-parent</artifactId>
+ <artifactId>json-common</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<packaging>jar</packaging>
- <name>json-common ${project.version}</name>
- <description>jsonUtil for Seata modules</description>
+ <name>json-common-core ${project.version}</name>
+ <description>jsonUtil core for Seata modules</description>
<dependencies>
<dependency>
@@ -47,6 +47,11 @@
<artifactId>fastjson</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>com.alibaba.fastjson2</groupId>
+ <artifactId>fastjson2</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -59,6 +64,4 @@
</dependency>
</dependencies>
-
-
-</project>
\ No newline at end of file
+</project>
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
similarity index 100%
rename from
json-common/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/JsonSerializer.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializer.java
similarity index 100%
rename from
json-common/src/main/java/org/apache/seata/common/json/JsonSerializer.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializer.java
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
similarity index 63%
rename from
json-common/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
index bc2cee5847..9d65c3de50 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
+++
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
@@ -18,6 +18,8 @@ package org.apache.seata.common.json;
import org.apache.seata.common.loader.EnhancedServiceLoader;
import org.apache.seata.common.util.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Optional;
@@ -25,8 +27,12 @@ import java.util.concurrent.ConcurrentHashMap;
public class JsonSerializerFactory {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(JsonSerializerFactory.class);
+
private static final String DEFAULT_SERIALIZER = "jackson";
+ private static final String JACKSON3_SERIALIZER = "jackson3";
+
private static final Map<String, JsonSerializer> INSTANCES = new
ConcurrentHashMap<>();
private JsonSerializerFactory() {}
@@ -34,12 +40,21 @@ public class JsonSerializerFactory {
/**
* Get JsonSerializer instance by name.
*
- * @param name the serializer name (e.g., "fastjson", "jackson", "gson")
+ * @param name the serializer name (e.g., "fastjson", "fastjson2",
"jackson", "jackson3", "gson")
* @return the JsonSerializer instance
*/
public static JsonSerializer getSerializer(String name) {
final String serializerName =
Optional.ofNullable(name).orElse(DEFAULT_SERIALIZER);
- return CollectionUtils.computeIfAbsent(
- INSTANCES, serializerName, key ->
EnhancedServiceLoader.load(JsonSerializer.class, key));
+ return CollectionUtils.computeIfAbsent(INSTANCES, serializerName, key
-> {
+ try {
+ return EnhancedServiceLoader.load(JsonSerializer.class, key);
+ } catch (Exception e) {
+ if (JACKSON3_SERIALIZER.equals(key)) {
+ LOGGER.warn("Jackson3 serializer is not available
(requires JDK 17+), falling back to jackson.", e);
+ return EnhancedServiceLoader.load(JsonSerializer.class,
DEFAULT_SERIALIZER);
+ }
+ throw e;
+ }
+ });
}
}
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/JsonUtil.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonUtil.java
similarity index 100%
rename from json-common/src/main/java/org/apache/seata/common/json/JsonUtil.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonUtil.java
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
similarity index 55%
copy from
json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
copy to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
index 42422a639c..f5599b267c 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
+++
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
@@ -16,66 +16,47 @@
*/
package org.apache.seata.common.json.impl;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.parser.Feature;
-import com.alibaba.fastjson.parser.ParserConfig;
-import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler;
+import com.alibaba.fastjson2.util.TypeUtils;
import org.apache.seata.common.exception.JsonParseException;
import org.apache.seata.common.json.JsonAllowlistManager;
import org.apache.seata.common.json.JsonSerializer;
import org.apache.seata.common.loader.LoadLevel;
import java.lang.reflect.Type;
+import java.util.regex.Pattern;
/**
- * FastJSON implementation of JsonSerializer
+ * Fastjson2 implementation of JsonSerializer
*/
-@LoadLevel(name = FastjsonJsonSerializer.NAME)
-public class FastjsonJsonSerializer implements JsonSerializer {
-
- private static final SerializerFeature[] SERIALIZER_FEATURES = new
SerializerFeature[] {
- SerializerFeature.DisableCircularReferenceDetect,
- SerializerFeature.WriteDateUseDateFormat,
- SerializerFeature.WriteClassName
- };
-
- private static final SerializerFeature[] SERIALIZER_FEATURES_PRETTY = new
SerializerFeature[] {
- SerializerFeature.DisableCircularReferenceDetect,
- SerializerFeature.WriteDateUseDateFormat,
- SerializerFeature.WriteClassName,
- SerializerFeature.PrettyFormat
- };
-
- private static final SerializerFeature[] FEATURES_PRETTY = new
SerializerFeature[] {
- SerializerFeature.DisableCircularReferenceDetect,
- SerializerFeature.WriteDateUseDateFormat,
- SerializerFeature.PrettyFormat
- };
-
- private static final Feature[] READER_FEATURES_SUPPORT_AUTO_TYPE =
- new Feature[] {Feature.SupportAutoType, Feature.OrderedField};
-
- private static final Feature[] READER_FEATURES_IGNORE_AUTO_TYPE =
- new Feature[] {Feature.IgnoreAutoType, Feature.OrderedField};
-
- private static final ParserConfig ALLOWLIST_PARSER_CONFIG = new
ParserConfig();
-
- static {
- ALLOWLIST_PARSER_CONFIG.setAutoTypeSupport(true);
- ALLOWLIST_PARSER_CONFIG.addAutoTypeCheckHandler((typeName,
expectClass, features) -> {
- JsonAllowlistManager.getInstance().checkClass(typeName);
- return null;
- });
- }
+@LoadLevel(name = Fastjson2JsonSerializer.NAME)
+public class Fastjson2JsonSerializer implements JsonSerializer {
+
+ public static final String NAME = "fastjson2";
+
+ private static final Pattern AUTOTYPE_PATTERN =
Pattern.compile("\"@type\"\\s*:");
- public static final String NAME = "fastjson";
+ private static final JSONWriter.Feature[] SERIALIZER_FEATURES =
+ new JSONWriter.Feature[] {JSONWriter.Feature.WriteClassName};
+
+ private static final JSONWriter.Feature[] SERIALIZER_FEATURES_PRETTY =
+ new JSONWriter.Feature[] {JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.PrettyFormat};
+
+ private static final JSONWriter.Feature[] FEATURES_PRETTY =
+ new JSONWriter.Feature[] {JSONWriter.Feature.PrettyFormat};
+
+ private static final AllowlistAutoTypeHandler ALLOWLIST_HANDLER =
+ new AllowlistAutoTypeHandler("org.apache.seata.", "io.seata.");
@Override
public String toJSONString(Object object) {
try {
- return JSON.toJSONString(object);
+ return JSON.toJSONString(object, SERIALIZER_FEATURES);
} catch (Exception e) {
- throw new JsonParseException("FastJSON serialize error", e);
+ throw new JsonParseException("Fastjson2 serialize error", e);
}
}
@@ -87,7 +68,7 @@ public class FastjsonJsonSerializer implements JsonSerializer
{
try {
return JSON.parseObject(text, clazz);
} catch (Exception e) {
- throw new JsonParseException("FastJSON deserialize error", e);
+ throw new JsonParseException("Fastjson2 deserialize error", e);
}
}
@@ -97,19 +78,18 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
return null;
}
try {
- return JSON.parseObject(text, type, ALLOWLIST_PARSER_CONFIG,
Feature.SupportAutoType, Feature.OrderedField);
+ return JSON.parseObject(text, type, ALLOWLIST_HANDLER,
JSONReader.Feature.SupportAutoType);
} catch (SecurityException e) {
throw e;
} catch (Exception e) {
rethrowIfSecurityException(e);
- throw new JsonParseException("FastJSON deserialize error", e);
+ throw new JsonParseException("Fastjson2 deserialize error", e);
}
}
- // advanced methods for Saga
@Override
public boolean useAutoType(String json) {
- return json != null && json.contains("\"@type\"");
+ return json != null && AUTOTYPE_PATTERN.matcher(json).find();
}
@Override
@@ -134,7 +114,7 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
}
}
} catch (Exception e) {
- throw new JsonParseException("FastJSON serialize error", e);
+ throw new JsonParseException("Fastjson2 serialize error", e);
}
}
@@ -144,21 +124,20 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
return null;
}
try {
- if ("[]".equals(text)) {
+ if ("[]".equals(text) &&
(java.util.Collection.class.isAssignableFrom(type) || type == Object.class)) {
return (T) new java.util.ArrayList<>();
}
if (ignoreAutoType) {
- return JSON.parseObject(text, type,
READER_FEATURES_IGNORE_AUTO_TYPE);
+ return JSON.parseObject(text, type);
} else {
- return JSON.parseObject(
- text, type, ALLOWLIST_PARSER_CONFIG,
Feature.SupportAutoType, Feature.OrderedField);
+ return JSON.parseObject(text, type, ALLOWLIST_HANDLER,
JSONReader.Feature.SupportAutoType);
}
} catch (SecurityException e) {
throw e;
} catch (Exception e) {
rethrowIfSecurityException(e);
- throw new JsonParseException("FastJSON deserialize error", e);
+ throw new JsonParseException("Fastjson2 deserialize error", e);
}
}
@@ -171,4 +150,28 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
cause = cause.getCause();
}
}
+
+ /**
+ * Extends ContextAutoTypeBeforeHandler (like Dubbo) for hash-optimized
prefix matching.
+ * Built-in basic types are included via includeBasic=true, seata prefixes
are passed
+ * to the constructor. User-defined allowlist entries are checked via
JsonAllowlistManager fallback.
+ */
+ private static class AllowlistAutoTypeHandler extends
ContextAutoTypeBeforeHandler {
+
+ AllowlistAutoTypeHandler(String... acceptNames) {
+ super(true, acceptNames);
+ }
+
+ @Override
+ public Class<?> apply(String typeName, Class<?> expectClass, long
features) {
+ Class<?> clazz = super.apply(typeName, expectClass, features);
+ if (clazz != null) {
+ return clazz;
+ }
+
+ // Throws SecurityException if not allowed
+ JsonAllowlistManager.getInstance().checkClass(typeName);
+ return TypeUtils.loadClass(typeName);
+ }
+ }
}
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
similarity index 95%
rename from
json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
index 42422a639c..d7f09d3db6 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
+++
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
@@ -26,6 +26,7 @@ import org.apache.seata.common.json.JsonSerializer;
import org.apache.seata.common.loader.LoadLevel;
import java.lang.reflect.Type;
+import java.util.regex.Pattern;
/**
* FastJSON implementation of JsonSerializer
@@ -33,6 +34,8 @@ import java.lang.reflect.Type;
@LoadLevel(name = FastjsonJsonSerializer.NAME)
public class FastjsonJsonSerializer implements JsonSerializer {
+ private static final Pattern AUTOTYPE_PATTERN =
Pattern.compile("\"@type\"\\s*:");
+
private static final SerializerFeature[] SERIALIZER_FEATURES = new
SerializerFeature[] {
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteDateUseDateFormat,
@@ -109,7 +112,7 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
// advanced methods for Saga
@Override
public boolean useAutoType(String json) {
- return json != null && json.contains("\"@type\"");
+ return json != null && AUTOTYPE_PATTERN.matcher(json).find();
}
@Override
@@ -144,7 +147,7 @@ public class FastjsonJsonSerializer implements
JsonSerializer {
return null;
}
try {
- if ("[]".equals(text)) {
+ if ("[]".equals(text) &&
(java.util.Collection.class.isAssignableFrom(type) || type == Object.class)) {
return (T) new java.util.ArrayList<>();
}
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
similarity index 96%
rename from
json-common/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
rename to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
index c04193a838..453f0ba399 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
+++
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
@@ -105,7 +105,7 @@ public class GsonJsonSerializer implements JsonSerializer {
return null;
}
try {
- if ("[]".equals(text)) {
+ if ("[]".equals(text) &&
(java.util.Collection.class.isAssignableFrom(type) || type == Object.class)) {
return (T) new java.util.ArrayList<>();
}
return gson.fromJson(text, type);
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
similarity index 96%
copy from
json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
copy to
json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
index 9986532cc1..a2df4fd455 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
+++
b/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
/**
* Jackson implementation of JsonSerializer
@@ -43,6 +44,8 @@ import java.util.List;
public class JacksonJsonSerializer implements JsonSerializer {
public static final String NAME = "jackson";
+ private static final Pattern AUTOTYPE_PATTERN =
Pattern.compile("\"@type\"\\s*:");
+
private final ObjectMapper defaultObjectMapper;
private final ObjectMapper objectMapperWithAutoType;
@@ -118,7 +121,7 @@ public class JacksonJsonSerializer implements
JsonSerializer {
// advanced methods for Saga
@Override
public boolean useAutoType(String json) {
- return json != null && json.contains("\"@type\"");
+ return json != null && AUTOTYPE_PATTERN.matcher(json).find();
}
@Override
@@ -158,7 +161,7 @@ public class JacksonJsonSerializer implements
JsonSerializer {
return null;
}
try {
- if ("[]".equals(json)) {
+ if ("[]".equals(json) &&
(java.util.Collection.class.isAssignableFrom(type) || type == Object.class)) {
return (T) new ArrayList<>(0);
}
if (ignoreAutoType) {
diff --git
a/json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
b/json-common/json-common-core/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
similarity index 89%
copy from
json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
copy to
json-common/json-common-core/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
index f723b14b68..ed39af9308 100644
---
a/json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
+++
b/json-common/json-common-core/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
@@ -15,5 +15,6 @@
# limitations under the License.
#
org.apache.seata.common.json.impl.FastjsonJsonSerializer
+org.apache.seata.common.json.impl.Fastjson2JsonSerializer
org.apache.seata.common.json.impl.JacksonJsonSerializer
org.apache.seata.common.json.impl.GsonJsonSerializer
\ No newline at end of file
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java
similarity index 94%
copy from
json-common/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
copy to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java
index fc792c4ad0..16f6e1b906 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java
@@ -25,15 +25,15 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
- * Tests for FastJSON serializer with allowlist security check
+ * Tests for Fastjson2 serializer with allowlist security check
*/
-public class FastjsonAllowlistTest {
+public class Fastjson2AllowlistTest {
private JsonSerializer jsonSerializer;
@BeforeEach
void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson");
+ jsonSerializer = JsonSerializerFactory.getSerializer("fastjson2");
}
@AfterEach
@@ -45,7 +45,7 @@ public class FastjsonAllowlistTest {
public void testParseObject_allowedSeataClass() {
String json =
-
"{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
+
"{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
AllowedTestClass result = jsonSerializer.parseObject(json,
AllowedTestClass.class, false);
@@ -122,8 +122,8 @@ public class FastjsonAllowlistTest {
@Test
public void testParseObject_multipleAutoTypes() {
- String json =
"{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$ContainerClass\","
- +
"\"inner\":{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
+ String json =
"{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$ContainerClass\","
+ +
"\"inner\":{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
ContainerClass result = jsonSerializer.parseObject(json,
ContainerClass.class, false);
@@ -133,7 +133,7 @@ public class FastjsonAllowlistTest {
@Test
public void testParseObject_multipleAutoTypes_oneNotAllowed() {
- String json =
"{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$ContainerClass\","
+ String json =
"{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$ContainerClass\","
+
"\"inner\":{\"@type\":\"com.malicious.EvilClass\",\"name\":\"evil\"}}";
assertThatThrownBy(() -> jsonSerializer.parseObject(json,
ContainerClass.class, false))
@@ -143,7 +143,6 @@ public class FastjsonAllowlistTest {
@Test
public void testParseObject_atTypeInStringValue_notBlocked() {
- // @type appearing inside a string value should not be treated as
AutoType metadata
String json = "{\"description\":\"the \\\"@type\\\" field is
important\",\"name\":\"test\"}";
TestObject result = jsonSerializer.parseObject(json, TestObject.class,
false);
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java
similarity index 73%
copy from
json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
copy to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java
index ff364e059b..060cdc0d20 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java
@@ -16,10 +16,9 @@
*/
package org.apache.seata.common.json;
-import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson2.TypeReference;
import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.FastjsonJsonSerializer;
-import org.apache.seata.common.json.impl.JacksonJsonSerializer;
+import org.apache.seata.common.json.impl.Fastjson2JsonSerializer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -30,14 +29,13 @@ import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-public class FastjsonJsonSerializerTest {
+public class Fastjson2JsonSerializerTest {
private JsonSerializer jsonSerializer;
@BeforeEach
void setUp() {
- // Use factory to get FastJSON serializer by name
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson");
+ jsonSerializer = JsonSerializerFactory.getSerializer("fastjson2");
}
@Test
@@ -89,7 +87,6 @@ public class FastjsonJsonSerializerTest {
String prettyJson = jsonSerializer.toJSONString(obj, true);
assertThat(prettyJson).contains("\n");
- assertThat(prettyJson).contains("\t");
}
@Test
@@ -144,28 +141,14 @@ public class FastjsonJsonSerializerTest {
public void testParseObject_invalidJson() {
assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}",
TestObject.class))
.isInstanceOf(JsonParseException.class)
- .hasMessageContaining("FastJSON deserialize error");
+ .hasMessageContaining("Fastjson2 deserialize error");
}
@Test
public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer =
JsonSerializerFactory.getSerializer("fastjson");
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("fastjson2");
assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(FastjsonJsonSerializer.class);
- }
-
- @Test
- public void testFactoryReturnsDefaultInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testToJSONString_emptyList() {
- List<String> emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
+ assertThat(serializer).isInstanceOf(Fastjson2JsonSerializer.class);
}
@Test
@@ -176,18 +159,6 @@ public class FastjsonJsonSerializerTest {
assertThat(jsonWithAutoType).contains("@type");
}
- @Test
- public void testParseObject_nullJson() {
- assertThat(jsonSerializer.parseObject(null, TestObject.class,
false)).isNull();
- }
-
- @Test
- public void testParseObject_emptyList() {
- String json = "[]";
- List<?> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
@Test
public void testParseObject_withAutoType() {
TestObject original = new TestObject("autoTypeTest", 999);
@@ -202,7 +173,6 @@ public class FastjsonJsonSerializerTest {
@Test
public void testParseObject_withType() {
-
String json = "{\"name\":\"test\",\"value\":123}";
Type type = new TypeReference<TestObject>() {}.getType();
@@ -221,8 +191,19 @@ public class FastjsonJsonSerializerTest {
}
@Test
- public void testParseObject_withIgnoreAutoType() {
+ public void testParseObject_nullJson() {
+ assertThat(jsonSerializer.parseObject(null, TestObject.class,
false)).isNull();
+ }
+ @Test
+ public void testParseObject_emptyList() {
+ String json = "[]";
+ List<?> list = jsonSerializer.parseObject(json, List.class, false);
+ assertThat(list).isEmpty();
+ }
+
+ @Test
+ public void testParseObject_withIgnoreAutoType() {
String jsonWithAutoType = jsonSerializer.toJSONString(new
TestObject("ignored", 222));
TestObject objIgnore = jsonSerializer.parseObject(jsonWithAutoType,
TestObject.class, true);
@@ -235,9 +216,6 @@ public class FastjsonJsonSerializerTest {
assertThat(objNoIgnore.getName()).isEqualTo("ignored");
assertThat(objNoIgnore.getValue()).isEqualTo(222);
- List<?> emptyListResult = jsonSerializer.parseObject("", List.class,
false);
- assertThat(emptyListResult).isNull();
-
List<?> emptyList = jsonSerializer.parseObject("[]", List.class,
false);
assertThat(emptyList).isEmpty();
@@ -245,7 +223,71 @@ public class FastjsonJsonSerializerTest {
assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}",
TestObject.class, false))
.isInstanceOf(JsonParseException.class)
- .hasMessageContaining("FastJSON deserialize error");
+ .hasMessageContaining("Fastjson2 deserialize error");
+ }
+
+ /**
+ * The "[]" shortcut in parseObject(String, Class, boolean) must only
apply when the
+ * target type is a Collection. Otherwise it would silently return an
empty ArrayList
+ * cast to T, causing a ClassCastException at the call site. The exact
behaviour of the
+ * underlying library when asked to map "[]" to a POJO may vary (return
null, return an
+ * empty POJO, or throw); the only requirement enforced here is that the
result is never
+ * an ArrayList.
+ */
+ @Test
+ public void
testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
+ assertEmptyArrayDoesNotProduceCollection(true);
+ assertEmptyArrayDoesNotProduceCollection(false);
+ }
+
+ private void assertEmptyArrayDoesNotProduceCollection(boolean
ignoreAutoType) {
+ Object result;
+ try {
+ result = jsonSerializer.parseObject("[]", TestObject.class,
ignoreAutoType);
+ } catch (JsonParseException ignored) {
+ // throwing is also an acceptable outcome
+ return;
+ }
+ if (result != null) {
+ assertThat(result).isNotInstanceOf(java.util.Collection.class);
+ }
+ }
+
+ @Test
+ public void testToJSONString_withIgnoreAutoTypeAndPrettyPrint() {
+ TestObject obj = new TestObject("noType", 111);
+
+ String jsonIgnorePretty = jsonSerializer.toJSONString(obj, true, true);
+ assertThat(jsonIgnorePretty).contains("\n");
+ assertThat(jsonIgnorePretty).doesNotContain("@type");
+
+ String jsonIgnoreNormal = jsonSerializer.toJSONString(obj, true,
false);
+ assertThat(jsonIgnoreNormal).doesNotContain("\n");
+ assertThat(jsonIgnoreNormal).doesNotContain("@type");
+
+ String jsonNoIgnorePretty = jsonSerializer.toJSONString(obj, false,
true);
+ assertThat(jsonNoIgnorePretty).contains("\n");
+ assertThat(jsonNoIgnorePretty).contains("@type");
+
+ String jsonNoIgnoreNormal = jsonSerializer.toJSONString(obj, false,
false);
+ assertThat(jsonNoIgnoreNormal).doesNotContain("\n");
+ assertThat(jsonNoIgnoreNormal).contains("@type");
+ }
+
+ @Test
+ public void testUseAutoType() {
+ String jsonWithAutoType =
"{\"@type\":\"some.type\",\"name\":\"test\"}";
+ assertThat(jsonSerializer.useAutoType(jsonWithAutoType)).isTrue();
+
+ String jsonWithoutAutoType = "{\"name\":\"test\"}";
+ assertThat(jsonSerializer.useAutoType(jsonWithoutAutoType)).isFalse();
+
+ String jsonWithTypeInValue = "{\"comment\":\"this has @type in it\"}";
+ assertThat(jsonSerializer.useAutoType(jsonWithTypeInValue)).isFalse();
+
+ assertThat(jsonSerializer.useAutoType(null)).isFalse();
+
+ assertThat(jsonSerializer.useAutoType("")).isFalse();
}
public static class TestObject {
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
similarity index 100%
rename from
json-common/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
rename to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
similarity index 87%
rename from
json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
rename to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
index ff364e059b..15f752fb35 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
@@ -83,6 +83,13 @@ public class FastjsonJsonSerializerTest {
assertThat(hasAutoType).isFalse();
}
+ @Test
+ public void testUseAutoType_typeInValue() {
+ String json = "{\"comment\":\"this has @type in it\"}";
+ boolean hasAutoType = jsonSerializer.useAutoType(json);
+ assertThat(hasAutoType).isFalse();
+ }
+
@Test
public void testToJSONString_prettyPrint() {
TestObject obj = new TestObject("pretty", 789);
@@ -248,6 +255,33 @@ public class FastjsonJsonSerializerTest {
.hasMessageContaining("FastJSON deserialize error");
}
+ /**
+ * The "[]" shortcut in parseObject(String, Class, boolean) must only
apply when the
+ * target type is a Collection. Otherwise it would silently return an
empty ArrayList
+ * cast to T, causing a ClassCastException at the call site. The exact
behaviour of the
+ * underlying library when asked to map "[]" to a POJO may vary (return
null, return an
+ * empty POJO, or throw); the only requirement enforced here is that the
result is never
+ * an ArrayList.
+ */
+ @Test
+ public void
testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
+ assertEmptyArrayDoesNotProduceCollection(true);
+ assertEmptyArrayDoesNotProduceCollection(false);
+ }
+
+ private void assertEmptyArrayDoesNotProduceCollection(boolean
ignoreAutoType) {
+ Object result;
+ try {
+ result = jsonSerializer.parseObject("[]", TestObject.class,
ignoreAutoType);
+ } catch (JsonParseException ignored) {
+ // throwing is also an acceptable outcome
+ return;
+ }
+ if (result != null) {
+ assertThat(result).isNotInstanceOf(java.util.Collection.class);
+ }
+ }
+
public static class TestObject {
private String name;
private int value;
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
similarity index 86%
rename from
json-common/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
rename to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
index b2b432acf3..ed2419912b 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
@@ -194,6 +194,33 @@ public class GsonJsonSerializerTest {
assertThat(list).isEmpty();
}
+ /**
+ * The "[]" shortcut in parseObject(String, Class, boolean) must only
apply when the
+ * target type is a Collection. Otherwise it would silently return an
empty ArrayList
+ * cast to T, causing a ClassCastException at the call site. The exact
behaviour of the
+ * underlying library when asked to map "[]" to a POJO may vary (return
null, return an
+ * empty POJO, or throw); the only requirement enforced here is that the
result is never
+ * an ArrayList.
+ */
+ @Test
+ public void
testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
+ assertEmptyArrayDoesNotProduceCollection(true);
+ assertEmptyArrayDoesNotProduceCollection(false);
+ }
+
+ private void assertEmptyArrayDoesNotProduceCollection(boolean
ignoreAutoType) {
+ Object result;
+ try {
+ result = jsonSerializer.parseObject("[]", TestObject.class,
ignoreAutoType);
+ } catch (JsonParseException ignored) {
+ // throwing is also an acceptable outcome
+ return;
+ }
+ if (result != null) {
+ assertThat(result).isNotInstanceOf(java.util.Collection.class);
+ }
+ }
+
@Test
public void testParseObject_withAutoType() {
TestObject original = new TestObject("autoTypeTest", 999);
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
similarity index 100%
copy from
json-common/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
copy to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
similarity index 88%
copy from
json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
copy to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
index 2b20a1e670..1433fb0ca2 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
@@ -83,6 +83,13 @@ public class JacksonJsonSerializerTest {
assertThat(hasAutoType).isFalse();
}
+ @Test
+ public void testUseAutoType_typeInValue() {
+ String json = "{\"comment\":\"this has @type in it\"}";
+ boolean hasAutoType = jsonSerializer.useAutoType(json);
+ assertThat(hasAutoType).isFalse();
+ }
+
@Test
public void testToJSONString_withAutoType() {
TestObject obj = new TestObject("withType", 789);
@@ -232,6 +239,10 @@ public class JacksonJsonSerializerTest {
boolean noAutoType = jsonSerializer.useAutoType(jsonWithoutAutoType);
assertThat(noAutoType).isFalse();
+ String jsonWithTypeInValue = "{\"comment\":\"this has @type in it\"}";
+ boolean typeInValue = jsonSerializer.useAutoType(jsonWithTypeInValue);
+ assertThat(typeInValue).isFalse();
+
boolean nullAutoType = jsonSerializer.useAutoType(null);
assertThat(nullAutoType).isFalse();
@@ -285,6 +296,33 @@ public class JacksonJsonSerializerTest {
.hasMessageContaining("Jackson serialize error");
}
+ /**
+ * The "[]" shortcut in parseObject(String, Class, boolean) must only
apply when the
+ * target type is a Collection. Otherwise it would silently return an
empty ArrayList
+ * cast to T, causing a ClassCastException at the call site. The exact
behaviour of the
+ * underlying library when asked to map "[]" to a POJO may vary (return
null, return an
+ * empty POJO, or throw); the only requirement enforced here is that the
result is never
+ * an ArrayList.
+ */
+ @Test
+ public void
testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
+ assertEmptyArrayDoesNotProduceCollection(true);
+ assertEmptyArrayDoesNotProduceCollection(false);
+ }
+
+ private void assertEmptyArrayDoesNotProduceCollection(boolean
ignoreAutoType) {
+ Object result;
+ try {
+ result = jsonSerializer.parseObject("[]", TestObject.class,
ignoreAutoType);
+ } catch (JsonParseException ignored) {
+ // throwing is also an acceptable outcome
+ return;
+ }
+ if (result != null) {
+ assertThat(result).isNotInstanceOf(java.util.Collection.class);
+ }
+ }
+
@Test
public void testParseObject_withIgnoreAutoType() {
String jsonWithAutoType = jsonSerializer.toJSONString(new
TestObject("ignored", 222), false, false);
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
similarity index 100%
rename from
json-common/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
rename to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
diff --git
a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java
new file mode 100644
index 0000000000..99a66966f3
--- /dev/null
+++
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.seata.common.json;
+
+import org.apache.seata.common.json.impl.Fastjson2JsonSerializer;
+import org.apache.seata.common.json.impl.FastjsonJsonSerializer;
+import org.apache.seata.common.json.impl.GsonJsonSerializer;
+import org.apache.seata.common.json.impl.JacksonJsonSerializer;
+import org.apache.seata.common.loader.EnhancedServiceNotFoundException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class JsonSerializerFactoryTest {
+
+ @BeforeEach
+ @SuppressWarnings("unchecked")
+ void clearInstancesCache() throws Exception {
+ Field field =
JsonSerializerFactory.class.getDeclaredField("INSTANCES");
+ field.setAccessible(true);
+ ((Map<String, JsonSerializer>) field.get(null)).clear();
+ }
+
+ @Test
+ public void testGetSerializer_jackson() {
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("jackson");
+
assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_fastjson() {
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("fastjson");
+
assertThat(serializer).isNotNull().isInstanceOf(FastjsonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_fastjson2() {
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("fastjson2");
+
assertThat(serializer).isNotNull().isInstanceOf(Fastjson2JsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_gson() {
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("gson");
+
assertThat(serializer).isNotNull().isInstanceOf(GsonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_nullName_returnsDefaultJackson() {
+ JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
+
assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_unknownName_throwsException() {
+ assertThatThrownBy(() ->
JsonSerializerFactory.getSerializer("definitely-not-a-real-serializer"))
+ .isInstanceOf(EnhancedServiceNotFoundException.class);
+ }
+
+ @Test
+ public void testGetSerializer_sameNameReturnsCachedInstance() {
+ JsonSerializer first = JsonSerializerFactory.getSerializer("jackson");
+ JsonSerializer second = JsonSerializerFactory.getSerializer("jackson");
+ assertThat(second).isSameAs(first);
+ }
+
+ /**
+ * In json-common-core tests, the jackson3 SPI lives in the separate
json-common-jackson3
+ * module which is NOT on the test classpath. The factory must catch the
+ * EnhancedServiceNotFoundException for "jackson3" and fall back to the
default "jackson"
+ * serializer.
+ */
+ @Test
+ public void testGetSerializer_jackson3_fallsBackToJacksonWhenUnavailable()
{
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("jackson3");
+
assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_jackson3FallbackIsCached() {
+ JsonSerializer first = JsonSerializerFactory.getSerializer("jackson3");
+ JsonSerializer second =
JsonSerializerFactory.getSerializer("jackson3");
+ assertThat(second).isSameAs(first);
+ assertThat(first).isInstanceOf(JacksonJsonSerializer.class);
+ }
+
+ @Test
+ public void testGetSerializer_jackson3FallbackIsUsableForSerialization() {
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("jackson3");
+ String json = serializer.toJSONString(new SimplePojo("hello", 7));
+
assertThat(json).contains("\"name\":\"hello\"").contains("\"value\":7");
+
+ SimplePojo restored = serializer.parseObject(json, SimplePojo.class);
+ assertThat(restored).isNotNull();
+ assertThat(restored.getName()).isEqualTo("hello");
+ assertThat(restored.getValue()).isEqualTo(7);
+ }
+
+ public static class SimplePojo {
+ private String name;
+ private int value;
+
+ public SimplePojo() {}
+
+ public SimplePojo(String name, int value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+ }
+}
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
similarity index 100%
rename from
json-common/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
rename to
json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
diff --git a/json-common/src/test/resources/file.conf
b/json-common/json-common-core/src/test/resources/file.conf
similarity index 100%
rename from json-common/src/test/resources/file.conf
rename to json-common/json-common-core/src/test/resources/file.conf
diff --git a/json-common/src/test/resources/registry.conf
b/json-common/json-common-core/src/test/resources/registry.conf
similarity index 100%
rename from json-common/src/test/resources/registry.conf
rename to json-common/json-common-core/src/test/resources/registry.conf
diff --git
a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
b/json-common/json-common-jackson3/pom.xml
similarity index 66%
copy from seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
copy to json-common/json-common-jackson3/pom.xml
index 858ae42537..da4d5c4832 100644
--- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
+++ b/json-common/json-common-jackson3/pom.xml
@@ -21,30 +21,33 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>seata-spring-autoconfigure</artifactId>
<groupId>org.apache.seata</groupId>
+ <artifactId>json-common</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+ <artifactId>json-common-jackson3</artifactId>
+ <packaging>jar</packaging>
+ <name>json-common-jackson3 ${project.version}</name>
+ <description>Jackson 3 JSON serializer for Seata (requires JDK
17+)</description>
- <artifactId>seata-spring-autoconfigure-client</artifactId>
- <name>seata-spring-autoconfigure-client ${project.version}</name>
- <description>spring-autoconfigure-client for Seata built with
Maven</description>
+ <properties>
+ <java.version>17</java.version>
+ <maven.compiler.source>17</maven.compiler.source>
+ <maven.compiler.target>17</maven.compiler.target>
+ </properties>
<dependencies>
<dependency>
- <groupId>org.apache.seata</groupId>
- <artifactId>seata-spring-autoconfigure-core</artifactId>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.seata</groupId>
- <artifactId>json-common</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>javax.annotation</groupId>
- <artifactId>javax.annotation-api</artifactId>
+ <groupId>tools.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>provided</scope>
</dependency>
</dependencies>
-</project>
\ No newline at end of file
+
+</project>
diff --git
a/json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
b/json-common/json-common-jackson3/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
similarity index 50%
rename from
json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
rename to
json-common/json-common-jackson3/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
index 9986532cc1..86c361a3b9 100644
---
a/json-common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
+++
b/json-common/json-common-jackson3/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
@@ -16,75 +16,59 @@
*/
package org.apache.seata.common.json.impl;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
-import com.fasterxml.jackson.databind.cfg.MapperConfig;
-import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import org.apache.seata.common.exception.JsonParseException;
import org.apache.seata.common.json.JsonAllowlistManager;
import org.apache.seata.common.json.JsonSerializer;
import org.apache.seata.common.loader.LoadLevel;
+import tools.jackson.core.JacksonException;
+import tools.jackson.databind.DatabindContext;
+import tools.jackson.databind.DefaultTyping;
+import tools.jackson.databind.DeserializationFeature;
+import tools.jackson.databind.JavaType;
+import tools.jackson.databind.ObjectMapper;
+import tools.jackson.databind.json.JsonMapper;
+import tools.jackson.databind.jsontype.PolymorphicTypeValidator;
-import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
/**
- * Jackson implementation of JsonSerializer
+ * Jackson 3.x implementation of JsonSerializer
*/
-@LoadLevel(name = JacksonJsonSerializer.NAME)
-public class JacksonJsonSerializer implements JsonSerializer {
- public static final String NAME = "jackson";
+@LoadLevel(name = Jackson3JsonSerializer.NAME)
+public class Jackson3JsonSerializer implements JsonSerializer {
+
+ public static final String NAME = "jackson3";
+
+ private static final Pattern AUTOTYPE_PATTERN =
Pattern.compile("\"@type\"\\s*:");
private final ObjectMapper defaultObjectMapper;
private final ObjectMapper objectMapperWithAutoType;
- private final ObjectMapper mapper = new ObjectMapper();
-
- public JacksonJsonSerializer() {
- this.defaultObjectMapper = new ObjectMapper()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false)
- .disableDefaultTyping()
- .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER)
- .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ public Jackson3JsonSerializer() {
+ this.defaultObjectMapper = JsonMapper.builder()
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .build();
AllowlistTypeValidator validator = new AllowlistTypeValidator();
- ObjectMapper.DefaultTypeResolverBuilder typer =
- new
ObjectMapper.DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL, validator);
- typer.init(JsonTypeInfo.Id.CLASS, null);
- typer.inclusion(JsonTypeInfo.As.PROPERTY);
- typer.typeProperty("@type");
-
- this.objectMapperWithAutoType = new ObjectMapper()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false)
- .setDefaultTyping(typer)
- .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER)
- .setSerializationInclusion(JsonInclude.Include.NON_NULL);
-
-
this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- this.mapper.activateDefaultTyping(
- this.mapper.getPolymorphicTypeValidator(),
- ObjectMapper.DefaultTyping.NON_FINAL,
- JsonTypeInfo.As.PROPERTY);
-
this.mapper.setConfig(this.mapper.getSerializationConfig().with(MapperFeature.PROPAGATE_TRANSIENT_MARKER));
-
this.mapper.setConfig(this.mapper.getDeserializationConfig().with(MapperFeature.PROPAGATE_TRANSIENT_MARKER));
- this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ this.objectMapperWithAutoType = JsonMapper.builder()
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .activateDefaultTypingAsProperty(validator,
DefaultTyping.NON_FINAL, "@type")
+ .build();
}
@Override
public String toJSONString(Object object) {
try {
- return mapper.writeValueAsString(object);
- } catch (JsonProcessingException e) {
- throw new JsonParseException("Jackson serialize error", e);
+ if (object instanceof List && ((List<?>) object).isEmpty()) {
+ return "[]";
+ }
+ return objectMapperWithAutoType.writeValueAsString(object);
+ } catch (JacksonException e) {
+ throw new JsonParseException("Jackson3 serialize error", e);
}
}
@@ -95,8 +79,8 @@ public class JacksonJsonSerializer implements JsonSerializer {
}
try {
return defaultObjectMapper.readValue(text, clazz);
- } catch (IOException e) {
- throw new JsonParseException("Jackson deserialize error", e);
+ } catch (JacksonException e) {
+ throw new JsonParseException("Jackson3 deserialize error", e);
}
}
@@ -109,16 +93,15 @@ public class JacksonJsonSerializer implements
JsonSerializer {
return objectMapperWithAutoType.readValue(text,
objectMapperWithAutoType.constructType(type));
} catch (SecurityException e) {
throw e;
- } catch (IOException e) {
+ } catch (JacksonException e) {
rethrowIfSecurityException(e);
- throw new JsonParseException("Jackson deserialize error", e);
+ throw new JsonParseException("Jackson3 deserialize error", e);
}
}
- // advanced methods for Saga
@Override
public boolean useAutoType(String json) {
- return json != null && json.contains("\"@type\"");
+ return json != null && AUTOTYPE_PATTERN.matcher(json).find();
}
@Override
@@ -132,23 +115,14 @@ public class JacksonJsonSerializer implements
JsonSerializer {
if (o instanceof List && ((List<?>) o).isEmpty()) {
return "[]";
}
+ ObjectMapper mapper = ignoreAutoType ? defaultObjectMapper :
objectMapperWithAutoType;
if (prettyPrint) {
- if (ignoreAutoType) {
- return
defaultObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
- } else {
- return objectMapperWithAutoType
- .writerWithDefaultPrettyPrinter()
- .writeValueAsString(o);
- }
+ return
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} else {
- if (ignoreAutoType) {
- return defaultObjectMapper.writeValueAsString(o);
- } else {
- return objectMapperWithAutoType.writeValueAsString(o);
- }
+ return mapper.writeValueAsString(o);
}
- } catch (JsonProcessingException e) {
- throw new JsonParseException("Jackson serialize error", e);
+ } catch (JacksonException e) {
+ throw new JsonParseException("Jackson3 serialize error", e);
}
}
@@ -158,7 +132,7 @@ public class JacksonJsonSerializer implements
JsonSerializer {
return null;
}
try {
- if ("[]".equals(json)) {
+ if ("[]".equals(json) &&
(java.util.Collection.class.isAssignableFrom(type) || type == Object.class)) {
return (T) new ArrayList<>(0);
}
if (ignoreAutoType) {
@@ -168,9 +142,9 @@ public class JacksonJsonSerializer implements
JsonSerializer {
}
} catch (SecurityException e) {
throw e;
- } catch (IOException e) {
+ } catch (JacksonException e) {
rethrowIfSecurityException(e);
- throw new JsonParseException("Jackson deserialize error", e);
+ throw new JsonParseException("Jackson3 deserialize error", e);
}
}
@@ -184,23 +158,26 @@ public class JacksonJsonSerializer implements
JsonSerializer {
}
}
+ /**
+ * Jackson 3.x native PolymorphicTypeValidator that delegates to
JsonAllowlistManager
+ */
private static class AllowlistTypeValidator extends
PolymorphicTypeValidator.Base {
private static final long serialVersionUID = 1L;
@Override
- public Validity validateBaseType(MapperConfig<?> config, JavaType
baseType) {
+ public Validity validateBaseType(DatabindContext ctxt, JavaType
baseType) {
return Validity.INDETERMINATE;
}
@Override
- public Validity validateSubClassName(MapperConfig<?> config, JavaType
baseType, String subClassName) {
+ public Validity validateSubClassName(DatabindContext ctxt, JavaType
baseType, String subClassName) {
// Throws SecurityException if not allowed
JsonAllowlistManager.getInstance().checkClass(subClassName);
return Validity.ALLOWED;
}
@Override
- public Validity validateSubType(MapperConfig<?> config, JavaType
baseType, JavaType subType) {
+ public Validity validateSubType(DatabindContext ctxt, JavaType
baseType, JavaType subType) {
JsonAllowlistManager.getInstance().checkClass(subType.getRawClass().getName());
return Validity.ALLOWED;
}
diff --git
a/json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
b/json-common/json-common-jackson3/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
similarity index 82%
rename from
json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
rename to
json-common/json-common-jackson3/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
index f723b14b68..f396fca121 100644
---
a/json-common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
+++
b/json-common/json-common-jackson3/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
@@ -14,6 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-org.apache.seata.common.json.impl.FastjsonJsonSerializer
-org.apache.seata.common.json.impl.JacksonJsonSerializer
-org.apache.seata.common.json.impl.GsonJsonSerializer
\ No newline at end of file
+org.apache.seata.common.json.impl.Jackson3JsonSerializer
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
b/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
similarity index 89%
rename from
json-common/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
rename to
json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
index 522b301a08..418829c2cf 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
+++
b/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
@@ -24,15 +24,15 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
- * Tests for Jackson serializer with allowlist security check
+ * Tests for Jackson3 serializer with allowlist security check
*/
-public class JacksonAllowlistTest {
+public class Jackson3AllowlistTest {
private JsonSerializer jsonSerializer;
@BeforeEach
void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("jackson");
+ jsonSerializer = JsonSerializerFactory.getSerializer("jackson3");
}
@AfterEach
@@ -44,7 +44,7 @@ public class JacksonAllowlistTest {
public void testParseObject_allowedSeataClass() {
String json =
-
"{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
+
"{\"@type\":\"org.apache.seata.common.json.Jackson3AllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
AllowedTestClass result = jsonSerializer.parseObject(json,
AllowedTestClass.class, false);
@@ -122,9 +122,6 @@ public class JacksonAllowlistTest {
@Test
public void testParseObject_noAutoType_bypasses_check() {
- // Jackson's objectMapperWithAutoType requires @type for non-final
types,
- // so use the 2-arg parseObject (defaultObjectMapper, no AutoType) to
verify
- // that normal JSON without @type does not trigger any
SecurityException.
String json = "{\"name\":\"test\",\"value\":123}";
TestObject result = jsonSerializer.parseObject(json, TestObject.class);
@@ -136,8 +133,8 @@ public class JacksonAllowlistTest {
@Test
public void testParseObject_multipleAutoTypes() {
- String json =
"{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$ContainerClass\","
- +
"\"inner\":{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
+ String json =
"{\"@type\":\"org.apache.seata.common.json.Jackson3AllowlistTest$ContainerClass\","
+ +
"\"inner\":{\"@type\":\"org.apache.seata.common.json.Jackson3AllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
ContainerClass result = jsonSerializer.parseObject(json,
ContainerClass.class, false);
@@ -147,7 +144,7 @@ public class JacksonAllowlistTest {
@Test
public void testParseObject_multipleAutoTypes_oneNotAllowed() {
- String json =
"{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$ContainerClass\","
+ String json =
"{\"@type\":\"org.apache.seata.common.json.Jackson3AllowlistTest$ContainerClass\","
+
"\"inner\":{\"@type\":\"com.malicious.EvilClass\",\"name\":\"evil\"}}";
assertThatThrownBy(() -> jsonSerializer.parseObject(json,
ContainerClass.class, false))
@@ -157,10 +154,7 @@ public class JacksonAllowlistTest {
@Test
public void testParseObject_atTypeInStringValue_notBlocked() {
- // @type appearing inside a string value should not be treated as
AutoType metadata.
- // The JSON has a real @type for the root object (required by
Jackson's DefaultTyping),
- // and a fake @type inside a string value which should not be flagged.
- String json =
"{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$TestObject\","
+ String json =
"{\"@type\":\"org.apache.seata.common.json.Jackson3AllowlistTest$TestObject\","
+ "\"name\":\"the \\\"@type\\\" field is
important\",\"value\":123}";
TestObject result = jsonSerializer.parseObject(json, TestObject.class,
false);
diff --git
a/json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
b/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
similarity index 78%
rename from
json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
rename to
json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
index 2b20a1e670..89c7e6f183 100644
---
a/json-common/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
+++
b/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
@@ -16,11 +16,11 @@
*/
package org.apache.seata.common.json;
-import com.alibaba.fastjson.TypeReference;
import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.JacksonJsonSerializer;
+import org.apache.seata.common.json.impl.Jackson3JsonSerializer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import tools.jackson.core.type.TypeReference;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -29,14 +29,13 @@ import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-public class JacksonJsonSerializerTest {
+public class Jackson3JsonSerializerTest {
private JsonSerializer jsonSerializer;
@BeforeEach
void setUp() {
- // Use factory to get Jackson serializer by name
- jsonSerializer = JsonSerializerFactory.getSerializer("jackson");
+ jsonSerializer = JsonSerializerFactory.getSerializer("jackson3");
}
@Test
@@ -51,7 +50,7 @@ public class JacksonJsonSerializerTest {
@Test
public void testParseObject_basicObject() {
String json =
-
"{\"@class\":\"org.apache.seata.common.json.JacksonJsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
+
"{\"@type\":\"org.apache.seata.common.json.Jackson3JsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
TestObject obj = jsonSerializer.parseObject(json, TestObject.class);
assertThat(obj).isNotNull();
@@ -94,13 +93,27 @@ public class JacksonJsonSerializerTest {
assertThat(jsonWithAutoType).contains("\"value\":789");
}
+ @Test
+ public void testToJSONString_singleArg_containsAutoType() {
+ TestObject obj = new TestObject("singleArg", 321);
+ String json = jsonSerializer.toJSONString(obj);
+
+ assertThat(json).contains("@type");
+ assertThat(json).contains("\"name\":\"singleArg\"");
+ assertThat(json).contains("\"value\":321");
+ }
+
+ @Test
+ public void testEmptyList_toJSONString_singleArg() {
+ List<String> emptyList = new ArrayList<>();
+ assertThat(jsonSerializer.toJSONString(emptyList)).isEqualTo("[]");
+ }
+
@Test
public void testParseObject_withAutoType() {
TestObject original = new TestObject("autoTypeTest", 999);
- // Serialize with autoType enabled
String jsonWithAutoType = jsonSerializer.toJSONString(original, false,
false);
- // Deserialize with autoType enabled
TestObject restored = jsonSerializer.parseObject(jsonWithAutoType,
TestObject.class, false);
assertThat(restored).isNotNull();
@@ -141,45 +154,34 @@ public class JacksonJsonSerializerTest {
public void testParseObject_invalidJson() {
assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}",
TestObject.class))
.isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
+ .hasMessageContaining("Jackson3 deserialize error");
}
@Test
public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer =
JsonSerializerFactory.getSerializer("jackson");
+ JsonSerializer serializer =
JsonSerializerFactory.getSerializer("jackson3");
assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class);
+ assertThat(serializer).isInstanceOf(Jackson3JsonSerializer.class);
}
@Test
- public void testFactoryReturnsDefaultInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
- assertThat(serializer).isNotNull();
- }
-
- @Test
- public void testToJSONString_throwsException() {
- Object unserializable = new Object() {
- private final java.io.InputStream stream = System.in;
- };
+ public void testToJSONString_prettyPrint() {
+ TestObject obj = new TestObject("pretty", 789);
+ String prettyJson = jsonSerializer.toJSONString(obj, true);
- assertThatThrownBy(() -> jsonSerializer.toJSONString(unserializable))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson serialize error");
+ assertThat(prettyJson).contains("\n");
}
@Test
- public void testParseObject_nullText() {
- assertThat(jsonSerializer.parseObject(null, String.class)).isNull();
- }
+ public void testParseObject_ignoreAutoType() {
+ TestObject obj = new TestObject("ignored", 222);
+ String json = jsonSerializer.toJSONString(obj);
- @Test
- public void testToJSONString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, true);
+ TestObject restored = jsonSerializer.parseObject(json,
TestObject.class, true);
- // Pretty JSON should contain newlines and indentation
- assertThat(prettyJson).contains("\n");
+ assertThat(restored).isNotNull();
+ assertThat(restored.getName()).isEqualTo("ignored");
+ assertThat(restored.getValue()).isEqualTo(222);
}
@Test
@@ -194,22 +196,10 @@ public class JacksonJsonSerializerTest {
assertThat(list).isEmpty();
}
- @Test
- public void testParseObject_ignoreAutoType() {
- TestObject obj = new TestObject("ignored", 222);
- String json = jsonSerializer.toJSONString(obj);
-
- TestObject restored = jsonSerializer.parseObject(json,
TestObject.class, true);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("ignored");
- assertThat(restored.getValue()).isEqualTo(222);
- }
-
@Test
public void testParseObject_withType() {
String json =
-
"{\"@type\":\"org.apache.seata.common.json.JacksonJsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
+
"{\"@type\":\"org.apache.seata.common.json.Jackson3JsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
Type type = new TypeReference<TestObject>() {}.getType();
TestObject obj = jsonSerializer.parseObjectWithType(json, type);
@@ -219,24 +209,23 @@ public class JacksonJsonSerializerTest {
assertThatThrownBy(() -> jsonSerializer.parseObjectWithType("{invalid
json}", type))
.isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
+ .hasMessageContaining("Jackson3 deserialize error");
}
@Test
public void testUseAutoType() {
String jsonWithAutoType =
"{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(jsonWithAutoType);
- assertThat(hasAutoType).isTrue();
+ assertThat(jsonSerializer.useAutoType(jsonWithAutoType)).isTrue();
String jsonWithoutAutoType = "{\"name\":\"test\"}";
- boolean noAutoType = jsonSerializer.useAutoType(jsonWithoutAutoType);
- assertThat(noAutoType).isFalse();
+ assertThat(jsonSerializer.useAutoType(jsonWithoutAutoType)).isFalse();
- boolean nullAutoType = jsonSerializer.useAutoType(null);
- assertThat(nullAutoType).isFalse();
+ String jsonWithTypeInValue = "{\"comment\":\"this has @type in it\"}";
+ assertThat(jsonSerializer.useAutoType(jsonWithTypeInValue)).isFalse();
- boolean emptyAutoType = jsonSerializer.useAutoType("");
- assertThat(emptyAutoType).isFalse();
+ assertThat(jsonSerializer.useAutoType(null)).isFalse();
+
+ assertThat(jsonSerializer.useAutoType("")).isFalse();
}
@Test
@@ -275,14 +264,6 @@ public class JacksonJsonSerializerTest {
List<String> emptyList = new ArrayList<>();
String emptyListJson = jsonSerializer.toJSONString(emptyList, false,
false);
assertThat(emptyListJson).isEqualTo("[]");
-
- Object invalidObject = new Object() {
- private final java.io.InputStream stream = System.in;
- };
-
- assertThatThrownBy(() -> jsonSerializer.toJSONString(invalidObject,
false, false))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson serialize error");
}
@Test
@@ -309,7 +290,34 @@ public class JacksonJsonSerializerTest {
assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}",
TestObject.class, false))
.isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
+ .hasMessageContaining("Jackson3 deserialize error");
+ }
+
+ /**
+ * The "[]" shortcut in parseObject(String, Class, boolean) must only
apply when the
+ * target type is a Collection. Otherwise it would silently return an
empty ArrayList
+ * cast to T, causing a ClassCastException at the call site. The exact
behaviour of the
+ * underlying library when asked to map "[]" to a POJO may vary (return
null, return an
+ * empty POJO, or throw); the only requirement enforced here is that the
result is never
+ * an ArrayList.
+ */
+ @Test
+ public void
testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
+ assertEmptyArrayDoesNotProduceCollection(true);
+ assertEmptyArrayDoesNotProduceCollection(false);
+ }
+
+ private void assertEmptyArrayDoesNotProduceCollection(boolean
ignoreAutoType) {
+ Object result;
+ try {
+ result = jsonSerializer.parseObject("[]", TestObject.class,
ignoreAutoType);
+ } catch (JsonParseException ignored) {
+ // throwing is also an acceptable outcome
+ return;
+ }
+ if (result != null) {
+ assertThat(result).isNotInstanceOf(java.util.Collection.class);
+ }
}
public static class TestObject {
diff --git a/json-common/pom.xml b/json-common/pom.xml
index a1588df199..1c0d9a5b5f 100644
--- a/json-common/pom.xml
+++ b/json-common/pom.xml
@@ -27,38 +27,25 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>json-common</artifactId>
- <packaging>jar</packaging>
+ <packaging>pom</packaging>
<name>json-common ${project.version}</name>
- <description>jsonUtil for Seata modules</description>
-
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>seata-common</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>seata-core</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-
-
-
-</project>
\ No newline at end of file
+ <description>json-common top parent for Seata built with
Maven</description>
+
+ <modules>
+ <module>json-common-core</module>
+ </modules>
+
+ <profiles>
+ <!-- Jackson 3 requires JDK 17+: only build the jackson3 submodule on
JDK 17+ -->
+ <profile>
+ <id>JDK17Plus</id>
+ <activation>
+ <jdk>[17,)</jdk>
+ </activation>
+ <modules>
+ <module>json-common-jackson3</module>
+ </modules>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml
index 0b06d56132..c08172c294 100644
--- a/rm-datasource/pom.xml
+++ b/rm-datasource/pom.xml
@@ -161,7 +161,7 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
diff --git
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
index f723b14b68..ed39af9308 100644
---
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
+++
b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
@@ -15,5 +15,6 @@
# limitations under the License.
#
org.apache.seata.common.json.impl.FastjsonJsonSerializer
+org.apache.seata.common.json.impl.Fastjson2JsonSerializer
org.apache.seata.common.json.impl.JacksonJsonSerializer
org.apache.seata.common.json.impl.GsonJsonSerializer
\ No newline at end of file
diff --git
a/rm-datasource/src/test/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
b/rm-datasource/src/test/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
index f723b14b68..ed39af9308 100644
---
a/rm-datasource/src/test/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
+++
b/rm-datasource/src/test/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
@@ -15,5 +15,6 @@
# limitations under the License.
#
org.apache.seata.common.json.impl.FastjsonJsonSerializer
+org.apache.seata.common.json.impl.Fastjson2JsonSerializer
org.apache.seata.common.json.impl.JacksonJsonSerializer
org.apache.seata.common.json.impl.GsonJsonSerializer
\ No newline at end of file
diff --git a/saga/pom.xml b/saga/pom.xml
index a8b639e8b3..7d10c03591 100644
--- a/saga/pom.xml
+++ b/saga/pom.xml
@@ -50,7 +50,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
diff --git
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
index bcccc5d893..ccc2342ef4 100644
---
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
+++
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
@@ -19,7 +19,7 @@ package org.apache.seata.saga.statelang.parser;
/**
* Json Parser
*
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in
json-common-core module instead.
*/
@Deprecated
public interface JsonParser {
diff --git
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
index 31cf44e8ad..a8b4ab9e49 100644
---
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
+++
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
@@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentMap;
/**
* JsonParserFactory
*
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory}
in json-common module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory}
in json-common-core module instead.
*/
@Deprecated
public class JsonParserFactory {
diff --git
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
index 28f47eebd2..851e4d1bd6 100644
---
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
+++
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
@@ -25,7 +25,7 @@ import org.apache.seata.saga.statelang.parser.JsonParser;
/**
* JsonParser implement by Fastjson
*
- * @deprecated use {@link
org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common module
instead.
+ * @deprecated use {@link
org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common-core
module instead.
*/
@Deprecated
@LoadLevel(name = FastjsonParser.NAME)
diff --git
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
index 3d2db889dd..f79abf4566 100644
---
a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
+++
b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
@@ -32,7 +32,7 @@ import java.util.List;
/**
* JsonParser implement by Jackson
*
- * @deprecated use {@link
org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common module
instead.
+ * @deprecated use {@link
org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common-core
module instead.
*/
@Deprecated
@LoadLevel(name = JacksonJsonParser.NAME)
diff --git
a/saga/seata-saga-statelang/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
b/saga/seata-saga-statelang/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
index f723b14b68..ed39af9308 100644
---
a/saga/seata-saga-statelang/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
+++
b/saga/seata-saga-statelang/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
@@ -15,5 +15,6 @@
# limitations under the License.
#
org.apache.seata.common.json.impl.FastjsonJsonSerializer
+org.apache.seata.common.json.impl.Fastjson2JsonSerializer
org.apache.seata.common.json.impl.JacksonJsonSerializer
org.apache.seata.common.json.impl.GsonJsonSerializer
\ No newline at end of file
diff --git a/script/client/spring/application.properties
b/script/client/spring/application.properties
index dcac5bac1e..304018b02e 100755
--- a/script/client/spring/application.properties
+++ b/script/client/spring/application.properties
@@ -187,7 +187,7 @@ seata.json.allowlist=
seata.tcc.fence.log-table-name=tcc_fence_log
seata.tcc.fence.clean-period=1h
-#You can choose from the following options: fastjson, jackson, gson
+#You can choose from the following options: fastjson, fastjson2, jackson,
jackson3, gson
seata.tcc.context-json-parser-type=fastjson
diff --git a/script/client/spring/application.yml
b/script/client/spring/application.yml
index 2c549f5b06..396483d782 100755
--- a/script/client/spring/application.yml
+++ b/script/client/spring/application.yml
@@ -205,7 +205,7 @@ seata:
fence:
log-table-name: tcc_fence_log
clean-period: 1h
- # You can choose from the following options: fastjson, jackson, gson
+ # You can choose from the following options: fastjson, fastjson2, jackson,
jackson3, gson
context-json-parser-type: fastjson
saga:
enabled: false
diff --git a/script/config-center/config.txt b/script/config-center/config.txt
index c6435eee60..ec2d3f66e3 100644
--- a/script/config-center/config.txt
+++ b/script/config-center/config.txt
@@ -98,7 +98,7 @@ client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
-# You can choose from the following options: fastjson, jackson, gson
+# You can choose from the following options: fastjson, fastjson2, jackson,
jackson3, gson
tcc.contextJsonParserType=fastjson
#Log rule configuration, for client and server
diff --git
a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
index 858ae42537..f0c5fb6fa3 100644
--- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
+++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
@@ -39,7 +39,7 @@
</dependency>
<dependency>
<groupId>org.apache.seata</groupId>
- <artifactId>json-common</artifactId>
+ <artifactId>json-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
diff --git
a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json
b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 2130b92ea1..551f35ab8d 100644
---
a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++
b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -372,8 +372,14 @@
"value": "fastjson",
"description": "the default parser."
},
+ {
+ "value": "fastjson2"
+ },
{
"value": "jackson"
+ },
+ {
+ "value": "jackson3"
}
]
},
@@ -397,9 +403,15 @@
"value": "jackson",
"description": "the default serialization."
},
+ {
+ "value": "jackson3"
+ },
{
"value": "fastjson"
},
+ {
+ "value": "fastjson2"
+ },
{
"value": "kryo"
},
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
b/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
index 516a57accc..120e986f36 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
@@ -22,7 +22,7 @@ import org.apache.seata.common.loader.LoadLevel;
import org.apache.seata.integration.tx.api.json.JsonParser;
/**
- * @deprecated use {@link
org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common module
instead.
+ * @deprecated use {@link
org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common-core
module instead.
*/
@Deprecated
@LoadLevel(name = Constants.FASTJSON_JSON_PARSER_NAME)
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
b/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
index 4ab84611ec..26caf1e678 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
@@ -25,7 +25,7 @@ import org.apache.seata.integration.tx.api.json.JsonParser;
import java.lang.reflect.Modifier;
/**
- * @deprecated use {@link
org.apache.seata.common.json.impl.GsonJsonSerializer} in json-common module
instead.
+ * @deprecated use {@link
org.apache.seata.common.json.impl.GsonJsonSerializer} in json-common-core
module instead.
*/
@Deprecated
@LoadLevel(name = Constants.GSON_JSON_PARSER_NAME)
diff --git
a/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
b/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
index 82b7a5f996..ea33594c24 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
@@ -28,7 +28,7 @@ import org.apache.seata.integration.tx.api.json.JsonParser;
import java.io.IOException;
/**
- * @deprecated use {@link
org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common module
instead.
+ * @deprecated use {@link
org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common-core
module instead.
*/
@Deprecated
@LoadLevel(name = Constants.JACKSON_JSON_PARSER_NAME)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]