From f9eec856e79ca1474b7659711a05026d756b157b Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 25 Sep 2025 10:50:34 +0000 Subject: [PATCH] =?UTF-8?q?!769=20update=20=E6=B7=BB=E5=8A=A0=20JSON=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E6=A0=A1=E9=AA=8C=E6=B3=A8=E8=A7=A3=E5=8F=8A?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20*=20update=20=E6=B7=BB=E5=8A=A0=20JSON=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E6=A0=A1=E9=AA=8C=E6=B3=A8=E8=A7=A3=E5=8F=8A?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/json/utils/JsonUtils.java | 55 +++++++++++++++++++ .../common/json/validate/JsonPattern.java | 33 +++++++++++ .../json/validate/JsonPatternValidator.java | 51 +++++++++++++++++ .../common/json/validate/JsonType.java | 30 ++++++++++ .../dromara/system/domain/bo/SysMenuBo.java | 3 + 5 files changed, 172 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPattern.java create mode 100644 ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPatternValidator.java create mode 100644 ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonType.java diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/utils/JsonUtils.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/utils/JsonUtils.java index 65c2faaed..837e15df5 100644 --- a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/utils/JsonUtils.java +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/utils/JsonUtils.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import lombok.AccessLevel; @@ -167,4 +168,58 @@ public class JsonUtils { } } + /** + * 判断字符串是否为合法 JSON(对象或数组) + * + * @param str 待校验字符串 + * @return true = 合法 JSON,false = 非法或空 + */ + public static boolean isJson(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + try { + OBJECT_MAPPER.readTree(str); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * 判断字符串是否为 JSON 对象({}) + * + * @param str 待校验字符串 + * @return true = JSON 对象 + */ + public static boolean isJsonObject(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + try { + JsonNode node = OBJECT_MAPPER.readTree(str); + return node.isObject(); + } catch (Exception e) { + return false; + } + } + + /** + * 判断字符串是否为 JSON 数组([]) + * + * @param str 待校验字符串 + * @return true = JSON 数组 + */ + public static boolean isJsonArray(String str) { + if (StringUtils.isBlank(str)) { + return false; + } + try { + JsonNode node = OBJECT_MAPPER.readTree(str); + return node.isArray(); + } catch (Exception e) { + return false; + } + } + } diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPattern.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPattern.java new file mode 100644 index 000000000..9b9538fc9 --- /dev/null +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPattern.java @@ -0,0 +1,33 @@ +package org.dromara.common.json.validate; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +/** + * JSON 格式校验注解 + * + * @author AprilWind + */ +@Documented +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = JsonPatternValidator.class) +public @interface JsonPattern { + + /** + * 限制 JSON 类型,默认为 {@link JsonType#ANY},即对象或数组都允许 + */ + JsonType type() default JsonType.ANY; + + /** + * 校验失败时的提示消息 + */ + String message() default "不是有效的 JSON 格式"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPatternValidator.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPatternValidator.java new file mode 100644 index 000000000..8747fa386 --- /dev/null +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonPatternValidator.java @@ -0,0 +1,51 @@ +package org.dromara.common.json.validate; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.json.utils.JsonUtils; + +/** + * JSON 格式校验器 + * + * @author AprilWind + */ +public class JsonPatternValidator implements ConstraintValidator { + + /** + * 注解中指定的 JSON 类型枚举 + */ + private JsonType jsonType; + + /** + * 初始化校验器,从注解中提取 JSON 类型 + * + * @param annotation 注解实例 + */ + @Override + public void initialize(JsonPattern annotation) { + this.jsonType = annotation.type(); + } + + /** + * 校验字符串是否为合法 JSON + * + * @param value 待校验字符串 + * @param context 校验上下文,可用于自定义错误信息 + * @return true = 合法 JSON 或为空,false = 非法 JSON + */ + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (StringUtils.isBlank(value)) { + // 交给 @NotBlank 或 @NotNull 控制是否允许为空 + return true; + } + // 根据 JSON 类型进行不同的校验 + return switch (jsonType) { + case ANY -> JsonUtils.isJson(value); + case OBJECT -> JsonUtils.isJsonObject(value); + case ARRAY -> JsonUtils.isJsonArray(value); + }; + } + +} diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonType.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonType.java new file mode 100644 index 000000000..6ac53e433 --- /dev/null +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/validate/JsonType.java @@ -0,0 +1,30 @@ +package org.dromara.common.json.validate; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * JSON 类型枚举 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum JsonType { + + /** + * JSON 对象,例如 {"a":1} + */ + OBJECT, + + /** + * JSON 数组,例如 [1,2,3] + */ + ARRAY, + + /** + * 任意 JSON 类型,对象或数组都可以 + */ + ANY + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysMenuBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysMenuBo.java index fbaafaa63..118c9544e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysMenuBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysMenuBo.java @@ -9,6 +9,8 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import org.dromara.common.core.constant.RegexConstants; +import org.dromara.common.json.validate.JsonPattern; +import org.dromara.common.json.validate.JsonType; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.system.domain.SysMenu; @@ -61,6 +63,7 @@ public class SysMenuBo extends BaseEntity { /** * 路由参数 */ + @JsonPattern(type = JsonType.OBJECT, message = "路由参数必须符合JSON格式") private String queryParam; /**