|
|
@@ -1,77 +1,106 @@
|
|
|
package com.jzg.commons.util;
|
|
|
|
|
|
+import cn.hutool.core.annotation.Alias;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
|
|
|
import io.swagger.v3.oas.annotations.media.Schema;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
|
|
|
public class SchemaDescriptionParser {
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(SchemaDescriptionParser.class);
|
|
|
/**
|
|
|
* 用于存储解析结果的缓存 Map
|
|
|
- * key: 字段名 (包括嵌套类的字段,格式为 "外层类名.内层类名.字段名")
|
|
|
- * value: @Schema 的 description 值
|
|
|
+ * key: 完全模拟 Hutool JSONUtil.toJsonStr() 序列化后的 Key
|
|
|
+ * value: @Schema 的 description 值;如果没有注解,则 value 等于 key
|
|
|
*/
|
|
|
private static final Map<String, String> SCHEMA_CACHE = new HashMap<>();
|
|
|
|
|
|
static {
|
|
|
try {
|
|
|
- // 初始化:解析目标类及其所有嵌套类
|
|
|
parseClassHierarchy(QuoteEchoVo.class, null);
|
|
|
|
|
|
- // 包装为不可变 Map,防止运行时被修改,提升安全性和性能
|
|
|
- // 注意:如果只需要在内部使用,可以保持 HashMap;如果对外暴露,建议 unmodifiableMap
|
|
|
+ log.info("初始化的SCHEMA_CACHE的大小是[{}]", CollUtil.size(SCHEMA_CACHE));
|
|
|
+ log.info("SCHEMA_CACHE.before=[{}]", JSONUtil.toJsonStr(SCHEMA_CACHE));
|
|
|
+ Map<String, String> otherMap = OrderComponents.fillKeyNameMap();
|
|
|
+ SCHEMA_CACHE.putAll(otherMap);
|
|
|
+ log.info("初始化的SCHEMA_CACHE的大小是[{}]. otherMap.size=[{}]", CollUtil.size(SCHEMA_CACHE), CollUtil.size(otherMap));
|
|
|
+ log.info("SCHEMA_CACHE.after=[{}]", JSONUtil.toJsonStr(SCHEMA_CACHE));
|
|
|
+ log.info("==============");
|
|
|
+ List<String> sortedKeys = new ArrayList<>(SCHEMA_CACHE.keySet()).stream().sorted().toList();
|
|
|
+ for (String sortedKey : sortedKeys) {
|
|
|
+ System.out.println(sortedKey);
|
|
|
+ }
|
|
|
+ log.info("==============");
|
|
|
+
|
|
|
+ log.info(">>>>>>>>>>>>>>>>>>>>>");
|
|
|
+ for (String s : otherMap.keySet().stream().toList().stream().sorted().toList()) {
|
|
|
+ System.out.println(s);
|
|
|
+ }
|
|
|
+ log.info(">>>>>>>>>>>>>>>>>>>>>");
|
|
|
+ log.info("sortedKeys=[{}]", JSONUtil.toJsonStr(sortedKeys));
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
|
- log.error("初始化Schema 描述映射失败", e);
|
|
|
- // 只初始化异常:记录错误但不中断程序启动
|
|
|
+ log.error("初始化 Schema 描述映射失败: ",e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 递归解析类及其内部类
|
|
|
- *
|
|
|
- * @param clazz 当前要解析的类
|
|
|
- * @param parentPrefix 父级类的前缀(用于区分嵌套类字段)
|
|
|
*/
|
|
|
private static void parseClassHierarchy(Class<?> clazz, String parentPrefix) {
|
|
|
if (clazz == null || clazz.isPrimitive() || clazz.getName().startsWith("java.")) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 获取当前类声明的所有字段(包括 private)
|
|
|
Field[] fields = clazz.getDeclaredFields();
|
|
|
|
|
|
for (Field field : fields) {
|
|
|
- // 1. 处理嵌套类 (Static Inner Classes)
|
|
|
- if (isStaticInnerClass(field.getType())) {
|
|
|
- // 构建新的前缀,例如 "InsOrders.InnerClass"
|
|
|
- String newPrefix = parentPrefix == null ? field.getType().getSimpleName() : parentPrefix + "." + field.getType().getSimpleName();
|
|
|
- parseClassHierarchy(field.getType(), newPrefix);
|
|
|
+ Class<?> fieldType = field.getType();
|
|
|
+
|
|
|
+ // 1. 处理内部类(嵌套对象)
|
|
|
+ if (fieldType.isMemberClass()) {
|
|
|
+ String jsonFieldName = resolveJsonFieldName(field);
|
|
|
+ String newPrefix = (parentPrefix == null ? "" : parentPrefix + ".") + jsonFieldName;
|
|
|
+ parseClassHierarchy(fieldType, newPrefix);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- // 2. 处理普通字段
|
|
|
+ // 2. 处理普通字段(无论有没有 @Schema 注解都会收录)
|
|
|
+ String jsonFieldName = resolveJsonFieldName(field);
|
|
|
+ String key = (parentPrefix == null ? "" : parentPrefix + ".") + jsonFieldName;
|
|
|
+
|
|
|
+ // 获取 @Schema 注解的 description
|
|
|
Schema schema = field.getAnnotation(Schema.class);
|
|
|
+ String value;
|
|
|
if (schema != null && !schema.description().isEmpty()) {
|
|
|
- String key = (parentPrefix == null ? "" : parentPrefix + ".") + field.getName();
|
|
|
- SCHEMA_CACHE.put(key, schema.description());
|
|
|
+ value = schema.description();
|
|
|
+ } else {
|
|
|
+ // 没有注解或 description 为空时,value 等于 key
|
|
|
+ value = key;
|
|
|
}
|
|
|
+
|
|
|
+ SCHEMA_CACHE.put(key, value);
|
|
|
}
|
|
|
- log.info("SCHEMA_CACHE map初始化完成。 大小是[{}]", CollUtil.size(SCHEMA_CACHE));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 判断是否为静态内部类
|
|
|
+ * 解析字段的 JSON Key 名称
|
|
|
+ * 模拟 Hutool JSONUtil.toJsonStr() 的行为:
|
|
|
+ * 1. 优先读取 @Alias 注解的值
|
|
|
+ * 2. 没有 @Alias 注解时,直接使用字段名
|
|
|
*/
|
|
|
- private static boolean isStaticInnerClass(Class<?> type) {
|
|
|
- return type.isMemberClass() && java.lang.reflect.Modifier.isStatic(type.getModifiers());
|
|
|
+ private static String resolveJsonFieldName(Field field) {
|
|
|
+ Alias alias = field.getAnnotation(Alias.class);
|
|
|
+ if (alias != null && !alias.value().isEmpty()) {
|
|
|
+ return alias.value();
|
|
|
+ }
|
|
|
+ return field.getName();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -84,6 +113,6 @@ public class SchemaDescriptionParser {
|
|
|
// --- 测试主函数 ---
|
|
|
public static void main(String[] args) {
|
|
|
Map<String, String> result = SchemaDescriptionParser.getSchemaMap();
|
|
|
- result.forEach((k, v) -> System.out.println(k + " = " + v));
|
|
|
+ //result.forEach((k, v) -> System.out.println(k + " = " + v));
|
|
|
}
|
|
|
-}
|
|
|
+}
|