diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java
index ac106ab3..86b5a793 100644
--- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java
+++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/domain/dto/request/ChatRequest.java
@@ -1,6 +1,5 @@
package org.ruoyi.common.chat.domain.dto.request;
-import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import dev.langchain4j.data.message.ChatMessage;
@@ -31,7 +30,6 @@ public class ChatRequest {
* 智能体ID。传入时后端按智能体配置解析模型/工具/技能/知识库/提示词/是否深度思考。
*/
@JsonSerialize(using = ToStringSerializer.class)
- @JSONField(serializeUsing = String.class)
private Long agentId;
/**
@@ -54,7 +52,6 @@ public class ChatRequest {
* 会话id
*/
@JsonSerialize(using = ToStringSerializer.class)
- @JSONField(serializeUsing = String.class)
private Long sessionId;
/**
@@ -71,7 +68,6 @@ public class ChatRequest {
* 对话id(每个聊天窗口都不一样)
*/
@JsonSerialize(using = ToStringSerializer.class)
- @JSONField(serializeUsing = String.class)
private Long uuid;
/**
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java
index f2a1f7b9..abfa3a95 100644
--- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java
@@ -1,6 +1,7 @@
package me.zhyd.oauth.request;
-import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthSource;
@@ -14,6 +15,9 @@ import me.zhyd.oauth.utils.HttpUtils;
import me.zhyd.oauth.utils.StringUtils;
import me.zhyd.oauth.utils.UrlBuilder;
+// 临时保留FastJson用于JustAuth库兼容
+import com.alibaba.fastjson.JSON;
+
/**
*
* 企业微信登录父类
@@ -37,11 +41,11 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
public AuthToken getAccessToken(AuthCallback authCallback) {
String response = doGetAuthorizationCode(accessTokenUrl(null));
- JSONObject object = this.checkResponse(response);
+ JsonNode object = this.checkResponse(response);
return AuthToken.builder()
- .accessToken(object.getString("access_token"))
- .expireIn(object.getIntValue("expires_in"))
+ .accessToken(object.get("access_token").asText())
+ .expireIn(object.get("expires_in").asInt())
.code(authCallback.getCode())
.build();
}
@@ -49,26 +53,29 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
@Override
public AuthUser getUserInfo(AuthToken authToken) {
String response = doGetUserInfo(authToken);
- JSONObject object = this.checkResponse(response);
+ JsonNode object = this.checkResponse(response);
// 返回 OpenId 或其他,均代表非当前企业用户,不支持
// https://github.com/justauth/JustAuth/issues/227 修复bug
- if (!object.containsKey("userid")) {
+ if (!object.has("userid")) {
throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, source);
}
- String userId = object.getString("userid");
- String userTicket = object.getString("user_ticket");
- JSONObject userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket);
+ String userId = object.get("userid").asText();
+ String userTicket = object.has("user_ticket") ? object.get("user_ticket").asText() : null;
+ JsonNode userDetail = getUserDetail(authToken.getAccessToken(), userId, userTicket);
+
+ // 将JsonNode转换为JSONObject以兼容JustAuth库
+ com.alibaba.fastjson.JSONObject rawUserInfo = com.alibaba.fastjson.JSON.parseObject(userDetail.toString());
return AuthUser.builder()
- .rawUserInfo(userDetail)
- .username(userDetail.getString("name"))
- .nickname(userDetail.getString("alias"))
- .avatar(userDetail.getString("avatar"))
- .location(userDetail.getString("address"))
- .email(userDetail.getString("email"))
+ .rawUserInfo(rawUserInfo)
+ .username(userDetail.has("name") ? userDetail.get("name").asText() : null)
+ .nickname(userDetail.has("alias") ? userDetail.get("alias").asText() : null)
+ .avatar(userDetail.has("avatar") ? userDetail.get("avatar").asText() : null)
+ .location(userDetail.has("address") ? userDetail.get("address").asText() : null)
+ .email(userDetail.has("email") ? userDetail.get("email").asText() : null)
.uuid(userId)
- .gender(AuthUserGender.getWechatRealGender(userDetail.getString("gender")))
+ .gender(AuthUserGender.getWechatRealGender(userDetail.has("gender") ? userDetail.get("gender").asText() : null))
.token(authToken)
.source(source.toString())
.build();
@@ -78,16 +85,21 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
* 校验请求结果
*
* @param response 请求结果
- * @return 如果请求结果正常,则返回JSONObject
+ * @return 如果请求结果正常,则返回JsonNode
*/
- private JSONObject checkResponse(String response) {
- JSONObject object = JSONObject.parseObject(response);
+ private JsonNode checkResponse(String response) {
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode object = objectMapper.readTree(response);
- if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
- throw new AuthException(object.getString("errmsg"), source);
+ if (object.has("errcode") && object.get("errcode").asInt() != 0) {
+ throw new AuthException(object.get("errmsg").asText(), source);
+ }
+
+ return object;
+ } catch (Exception e) {
+ throw new AuthException("解析响应失败: " + e.getMessage(), source);
}
-
- return object;
}
@@ -127,28 +139,39 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq
* @param userTicket 成员票据,用于获取用户信息或敏感信息
* @return 用户详情
*/
- private JSONObject getUserDetail(String accessToken, String userId, String userTicket) {
- // 用户基础信息
- String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
- .queryParam("access_token", accessToken)
- .queryParam("userid", userId)
- .build();
- String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
- JSONObject userInfo = checkResponse(userInfoResponse);
+ private JsonNode getUserDetail(String accessToken, String userId, String userTicket) {
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
- // 用户敏感信息
- if (StringUtils.isNotEmpty(userTicket)) {
- String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail")
+ // 用户基础信息
+ String userInfoUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/user/get")
.queryParam("access_token", accessToken)
+ .queryParam("userid", userId)
.build();
- JSONObject param = new JSONObject();
- param.put("user_ticket", userTicket);
- String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, param.toJSONString()).getBody();
- JSONObject userDetail = checkResponse(userDetailResponse);
+ String userInfoResponse = new HttpUtils(config.getHttpConfig()).get(userInfoUrl).getBody();
+ JsonNode userInfo = checkResponse(userInfoResponse);
- userInfo.putAll(userDetail);
+ // 用户敏感信息
+ if (StringUtils.isNotEmpty(userTicket)) {
+ String userDetailUrl = UrlBuilder.fromBaseUrl("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail")
+ .queryParam("access_token", accessToken)
+ .build();
+
+ // 构建请求参数
+ String paramJson = objectMapper.createObjectNode()
+ .put("user_ticket", userTicket)
+ .toString();
+
+ String userDetailResponse = new HttpUtils(config.getHttpConfig()).post(userDetailUrl, paramJson).getBody();
+ JsonNode userDetail = checkResponse(userDetailResponse);
+
+ // 合并两个JsonNode
+ ((com.fasterxml.jackson.databind.node.ObjectNode) userInfo).setAll((com.fasterxml.jackson.databind.node.ObjectNode) userDetail);
+ }
+ return userInfo;
+ } catch (Exception e) {
+ throw new AuthException("获取用户详情失败: " + e.getMessage(), source);
}
- return userInfo;
}
}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java
index 86532d48..1885b9f0 100644
--- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java
@@ -1,6 +1,7 @@
package me.zhyd.oauth.request;
-import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.xkcoding.http.support.HttpHeader;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
@@ -18,6 +19,9 @@ import me.zhyd.oauth.utils.UrlBuilder;
import java.util.HashMap;
import java.util.Map;
+// 临时保留FastJson用于JustAuth库兼容
+import com.alibaba.fastjson.JSON;
+
/**
* 新版钉钉二维码登录
*
@@ -52,44 +56,60 @@ public class AuthDingTalkV2Request extends AuthDefaultRequest {
@Override
public AuthToken getAccessToken(AuthCallback authCallback) {
- Map params = new HashMap<>();
- params.put("grantType", "authorization_code");
- params.put("clientId", config.getClientId());
- params.put("clientSecret", config.getClientSecret());
- params.put("code", authCallback.getCode());
- String response = new HttpUtils(config.getHttpConfig()).post(this.source.accessToken(), JSONObject.toJSONString(params)).getBody();
- JSONObject accessTokenObject = JSONObject.parseObject(response);
- if (!accessTokenObject.containsKey("accessToken")) {
- throw new AuthException(JSONObject.toJSONString(response), source);
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ Map params = new HashMap<>();
+ params.put("grantType", "authorization_code");
+ params.put("clientId", config.getClientId());
+ params.put("clientSecret", config.getClientSecret());
+ params.put("code", authCallback.getCode());
+
+ String paramsJson = objectMapper.writeValueAsString(params);
+ String response = new HttpUtils(config.getHttpConfig()).post(this.source.accessToken(), paramsJson).getBody();
+ JsonNode accessTokenObject = objectMapper.readTree(response);
+
+ if (!accessTokenObject.has("accessToken")) {
+ throw new AuthException(response, source);
+ }
+ return AuthToken.builder()
+ .accessToken(accessTokenObject.get("accessToken").asText())
+ .refreshToken(accessTokenObject.has("refreshToken") ? accessTokenObject.get("refreshToken").asText() : null)
+ .expireIn(accessTokenObject.has("expireIn") ? accessTokenObject.get("expireIn").asInt() : 0)
+ .corpId(accessTokenObject.has("corpId") ? accessTokenObject.get("corpId").asText() : null)
+ .build();
+ } catch (Exception e) {
+ throw new AuthException("获取AccessToken失败: " + e.getMessage(), source);
}
- return AuthToken.builder()
- .accessToken(accessTokenObject.getString("accessToken"))
- .refreshToken(accessTokenObject.getString("refreshToken"))
- .expireIn(accessTokenObject.getIntValue("expireIn"))
- .corpId(accessTokenObject.getString("corpId"))
- .build();
}
@Override
public AuthUser getUserInfo(AuthToken authToken) {
- HttpHeader header = new HttpHeader();
- header.add("x-acs-dingtalk-access-token", authToken.getAccessToken());
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ HttpHeader header = new HttpHeader();
+ header.add("x-acs-dingtalk-access-token", authToken.getAccessToken());
- String response = new HttpUtils(config.getHttpConfig()).get(this.source.userInfo(), null, header, false).getBody();
- JSONObject object = JSONObject.parseObject(response);
+ String response = new HttpUtils(config.getHttpConfig()).get(this.source.userInfo(), null, header, false).getBody();
+ JsonNode object = objectMapper.readTree(response);
- authToken.setOpenId(object.getString("openId"));
- authToken.setUnionId(object.getString("unionId"));
- return AuthUser.builder()
- .rawUserInfo(object)
- .uuid(object.getString("unionId"))
- .username(object.getString("nick"))
- .nickname(object.getString("nick"))
- .avatar(object.getString("avatarUrl"))
- .snapshotUser(object.getBooleanValue("visitor"))
- .token(authToken)
- .source(source.toString())
- .build();
+ // 将JsonNode转换为JSONObject以兼容JustAuth库
+ com.alibaba.fastjson.JSONObject rawUserInfo = com.alibaba.fastjson.JSON.parseObject(object.toString());
+
+ authToken.setOpenId(object.has("openId") ? object.get("openId").asText() : null);
+ authToken.setUnionId(object.has("unionId") ? object.get("unionId").asText() : null);
+ return AuthUser.builder()
+ .rawUserInfo(rawUserInfo)
+ .uuid(object.has("unionId") ? object.get("unionId").asText() : null)
+ .username(object.has("nick") ? object.get("nick").asText() : null)
+ .nickname(object.has("nick") ? object.get("nick").asText() : null)
+ .avatar(object.has("avatarUrl") ? object.get("avatarUrl").asText() : null)
+ .snapshotUser(object.has("visitor") && object.get("visitor").asBoolean())
+ .token(authToken)
+ .source(source.toString())
+ .build();
+ } catch (Exception e) {
+ throw new AuthException("获取用户信息失败: " + e.getMessage(), source);
+ }
}
/**
diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java
index f2482096..c8399aa8 100644
--- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java
+++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/mailSend/MailSendNode.java
@@ -1,8 +1,7 @@
package org.ruoyi.workflow.workflow.node.mailSend;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.JSONValidator;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -41,10 +40,15 @@ public class MailSendNode extends AbstractWfNode {
String input = getDataFromInput(inputs);
// 判断是否为JSON格式(LLM输出转换 由LLM生成格式)
if (StringUtils.isNotBlank(input) && isJson(input)) {
- JSONObject inputJson = JSON.parseObject(input);
- JSONObject configJson = (JSONObject) JSON.toJSON(config);
- configJson.putAll(inputJson);
- config = configJson.toJavaObject(MailSendNodeConfig.class);
+ // 使用Jackson解析和合并配置
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode inputJson = objectMapper.readTree(input);
+ // 将config转换为JsonNode
+ JsonNode configJson = objectMapper.valueToTree(config);
+ // 合并两个JSON节点
+ JsonNode mergedJson = objectMapper.readerForUpdating(configJson).readValue(inputJson);
+ // 转换回config对象
+ config = objectMapper.treeToValue(mergedJson, MailSendNodeConfig.class);
}
// 安全获取模板(使用 defaultString 避免 null)
@@ -217,9 +221,10 @@ public class MailSendNode extends AbstractWfNode {
if (str == null || str.trim().isEmpty()) {
return false;
}
- // 使用 try-with-resources 正确处理 JSONValidator 资源关闭
- try (JSONValidator validator = JSONValidator.from(str.trim())) {
- return validator.getType() == JSONValidator.Type.Object;
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.readTree(str.trim());
+ return true;
} catch (Exception e) {
log.warn("JSON格式校验失败: {}", e.getMessage());
return false;
diff --git a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/switcher/SwitcherNode.java b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/switcher/SwitcherNode.java
index f67d1585..4aece033 100644
--- a/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/switcher/SwitcherNode.java
+++ b/ruoyi-modules/ruoyi-aiflow/src/main/java/org/ruoyi/workflow/workflow/node/switcher/SwitcherNode.java
@@ -1,8 +1,7 @@
package org.ruoyi.workflow.workflow.node.switcher;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@@ -339,23 +338,26 @@ public class SwitcherNode extends AbstractWfNode {
String inputConfig = workflowNode.getInputConfig();
log.info("节点 '{}' 的输入配置: {}", nodeUuid, inputConfig);
if (StringUtils.isNotBlank(inputConfig)){
- // 解析输入配置为JSON对象
- JSONObject configJson = JSON.parseObject(inputConfig);
- // 获取 user_inputs 数组
- JSONArray userInputs = configJson.getJSONArray("user_inputs");
- if (userInputs != null && !userInputs.isEmpty()) {
- // 在 user_inputs 中查找匹配的参数名,并获取对应值
- Optional valueOpt = userInputs.stream()
- .filter(JSONObject.class::isInstance)
- .map(JSONObject.class::cast)
- .filter(obj -> paramName.equals(obj.getString("name")))
- .map(matchedObj -> getValueFromInputs(nodeUuid, "input", inputs))
- .filter(Objects::nonNull)
- .findFirst();
- // 若找到匹配值,则更新结果
- if (valueOpt.isPresent()) {
- result = valueOpt.get();
+ try {
+ // 使用Jackson解析输入配置
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode configJson = objectMapper.readTree(inputConfig);
+ // 获取 user_inputs 数组
+ JsonNode userInputs = configJson.get("user_inputs");
+ if (userInputs != null && userInputs.isArray()) {
+ // 在 user_inputs 中查找匹配的参数名,并获取对应值
+ for (JsonNode inputNode : userInputs) {
+ if (inputNode.has("name") && paramName.equals(inputNode.get("name").asText())) {
+ String value = getValueFromInputs(nodeUuid, "input", inputs);
+ if (value != null) {
+ result = value;
+ break;
+ }
+ }
+ }
}
+ } catch (Exception e) {
+ log.error("解析节点输入配置失败: {}", nodeUuid, e);
}
}
}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/utils/QwenFileUploadUtils.java b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/utils/QwenFileUploadUtils.java
index e4ea9ab5..4c75a0b2 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/utils/QwenFileUploadUtils.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/org/ruoyi/system/utils/QwenFileUploadUtils.java
@@ -1,6 +1,7 @@
package org.ruoyi.system.utils;
-import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.ruoyi.common.core.utils.StringUtils;
@@ -42,9 +43,11 @@ public class QwenFileUploadUtils {
if (StringUtils.isEmpty(responseBody)){
throw new ServerException("上传失败:响应体为空");
}
- JSONObject jsonObject = JSONObject.parseObject(responseBody);
+ // 使用Jackson解析JSON
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode jsonNode = objectMapper.readTree(responseBody);
// 千问返回的 fileId
- return jsonObject.getString("id");
+ return jsonNode.get("id").asText();
}
}
}