Преглед изворни кода

Update 添加JSON格式校验注解及实现

Yue пре 6 месеци
родитељ
комит
f55dce7e85

+ 55 - 2
SERVER/VberAdminPlusV3/vber-common/vber-common-core/src/main/java/com/vber/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 com.vber.common.core.utils.SpringUtils;
@@ -48,7 +49,6 @@ public class JsonUtils {
         }
     }
 
-
     /**
      * 将JSON格式的字符串转换为指定类型的对象
      *
@@ -69,7 +69,6 @@ public class JsonUtils {
         }
     }
 
-
     /**
      * 将字节数组转换为指定类型的对象
      *
@@ -169,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;
+        }
+    }
+
 }

+ 33 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-core/src/main/java/com/vber/common/json/validate/JsonPattern.java

@@ -0,0 +1,33 @@
+package com.vber.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<? extends Payload>[] payload() default {};
+
+}

+ 51 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-core/src/main/java/com/vber/common/json/validate/JsonPatternValidator.java

@@ -0,0 +1,51 @@
+package com.vber.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<JsonPattern, String> {
+
+    /**
+     * 注解中指定的 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);
+        };
+    }
+
+}

+ 30 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-core/src/main/java/com/vber/common/json/validate/JsonType.java

@@ -0,0 +1,30 @@
+package com.vber.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
+
+}

+ 3 - 0
SERVER/VberAdminPlusV3/vber-modules/vber-system/src/main/java/com/vber/system/domain/bo/SysMenuBo.java

@@ -1,6 +1,8 @@
 package com.vber.system.domain.bo;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.vber.common.json.validate.JsonPattern;
+import com.vber.common.json.validate.JsonType;
 import com.vber.common.mybatis.core.domain.BaseEntity;
 import com.vber.system.domain.SysMenu;
 import io.github.linpeilie.annotations.AutoMapper;
@@ -59,6 +61,7 @@ public class SysMenuBo extends BaseEntity {
     /**
      * 路由参数
      */
+    @JsonPattern(type = JsonType.OBJECT, message = "路由参数必须符合JSON格式")
     private String queryParam;
 
     /**