feat: 修改字段类型修改不生效的问题
All checks were successful
序列化结构检查 / serialization-schema-check (push) Has been skipped
All checks were successful
序列化结构检查 / serialization-schema-check (push) Has been skipped
This commit is contained in:
@@ -22,29 +22,41 @@ public class SchemaDiffer {
|
||||
public List<SchemaChange> diff(TypeSchema oldSchema, TypeSchema newSchema) {
|
||||
List<SchemaChange> changes = new ArrayList<>();
|
||||
|
||||
Map<String, JsonType> oldLeaves = leaves(oldSchema);
|
||||
Map<String, JsonType> newLeaves = leaves(newSchema);
|
||||
Map<String, FieldSchema> oldAll = fieldsByPath(oldSchema);
|
||||
Map<String, FieldSchema> newAll = fieldsByPath(newSchema);
|
||||
|
||||
Map<String, FieldSchema> oldLeaves = leaves(oldSchema);
|
||||
Map<String, FieldSchema> newLeaves = leaves(newSchema);
|
||||
|
||||
Set<String> typeChangedPaths = new LinkedHashSet<>();
|
||||
|
||||
// 类型变更:同路径下 JsonType 或 Java 类型任一变化(覆盖 BigDecimal→String 等同桶变更)
|
||||
for (String path : oldAll.keySet()) {
|
||||
FieldSchema oldField = oldAll.get(path);
|
||||
FieldSchema newField = newAll.get(path);
|
||||
if (newField == null) {
|
||||
continue;
|
||||
}
|
||||
if (!isTypeChange(oldField, newField)) {
|
||||
continue;
|
||||
}
|
||||
typeChangedPaths.add(path);
|
||||
String oldLabel = typeLabel(oldField);
|
||||
String newLabel = typeLabel(newField);
|
||||
SchemaChange c = new SchemaChange(ChangeType.TYPE_CHANGED);
|
||||
c.setFieldPath(path);
|
||||
c.setOldValue(oldLabel);
|
||||
c.setNewValue(newLabel);
|
||||
c.setMessage("字段 " + path + " 类型由 " + oldLabel + " 变为 " + newLabel);
|
||||
changes.add(c);
|
||||
}
|
||||
|
||||
Set<String> removed = new LinkedHashSet<>(oldLeaves.keySet());
|
||||
removed.removeAll(newLeaves.keySet());
|
||||
removed.removeAll(typeChangedPaths);
|
||||
Set<String> added = new LinkedHashSet<>(newLeaves.keySet());
|
||||
added.removeAll(oldLeaves.keySet());
|
||||
|
||||
// 类型变更(同路径)
|
||||
for (String path : oldLeaves.keySet()) {
|
||||
if (newLeaves.containsKey(path)) {
|
||||
JsonType oldType = oldLeaves.get(path);
|
||||
JsonType newType = newLeaves.get(path);
|
||||
if (oldType != newType) {
|
||||
SchemaChange c = new SchemaChange(ChangeType.TYPE_CHANGED);
|
||||
c.setFieldPath(path);
|
||||
c.setOldValue(oldType.name());
|
||||
c.setNewValue(newType.name());
|
||||
c.setMessage("字段 " + path + " 类型由 " + oldType + " 变为 " + newType);
|
||||
changes.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
added.removeAll(typeChangedPaths);
|
||||
|
||||
// 路径迁移检测(removed 的路径是某 added 路径的后缀)
|
||||
List<String[]> moves = new ArrayList<>();
|
||||
@@ -99,7 +111,7 @@ public class SchemaDiffer {
|
||||
}
|
||||
SchemaChange c = new SchemaChange(ChangeType.FIELD_REMOVED);
|
||||
c.setFieldPath(r);
|
||||
c.setOldValue(oldLeaves.get(r).name());
|
||||
c.setOldValue(typeLabel(oldLeaves.get(r)));
|
||||
c.setMessage("删除字段 " + r);
|
||||
changes.add(c);
|
||||
}
|
||||
@@ -111,7 +123,7 @@ public class SchemaDiffer {
|
||||
}
|
||||
SchemaChange c = new SchemaChange(ChangeType.FIELD_ADDED);
|
||||
c.setFieldPath(a);
|
||||
c.setNewValue(newLeaves.get(a).name());
|
||||
c.setNewValue(typeLabel(newLeaves.get(a)));
|
||||
c.setMessage("新增字段 " + a);
|
||||
changes.add(c);
|
||||
}
|
||||
@@ -119,11 +131,104 @@ public class SchemaDiffer {
|
||||
return changes;
|
||||
}
|
||||
|
||||
private Map<String, JsonType> leaves(TypeSchema schema) {
|
||||
Map<String, JsonType> result = new LinkedHashMap<>();
|
||||
private boolean isTypeChange(FieldSchema oldField, FieldSchema newField) {
|
||||
if (oldField.getJsonType() != newField.getJsonType()) {
|
||||
return true;
|
||||
}
|
||||
String oldJava = normalizeJavaType(oldField.getJavaType());
|
||||
String newJava = normalizeJavaType(newField.getJavaType());
|
||||
if (oldJava.isEmpty() || newJava.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return !oldJava.equals(newJava);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示用类型标签:优先 Java 简单名,并附带 JsonType(便于识别同桶变更)。
|
||||
*/
|
||||
private String typeLabel(FieldSchema field) {
|
||||
if (field == null) {
|
||||
return "?";
|
||||
}
|
||||
String java = simpleJavaType(field.getJavaType());
|
||||
JsonType json = field.getJsonType();
|
||||
if (java.isEmpty() || "?".equals(java)) {
|
||||
return json == null ? "?" : json.name();
|
||||
}
|
||||
if (json == null) {
|
||||
return java;
|
||||
}
|
||||
return java + "/" + json.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化后用于相等比较:去掉泛型与包名,基本类型与包装类型视为同一序列化类型。
|
||||
*/
|
||||
static String normalizeJavaType(String javaType) {
|
||||
String simple = simpleJavaType(javaType);
|
||||
if (simple.isEmpty() || "?".equals(simple)) {
|
||||
return "";
|
||||
}
|
||||
switch (simple) {
|
||||
case "int":
|
||||
return "Integer";
|
||||
case "long":
|
||||
return "Long";
|
||||
case "short":
|
||||
return "Short";
|
||||
case "byte":
|
||||
return "Byte";
|
||||
case "double":
|
||||
return "Double";
|
||||
case "float":
|
||||
return "Float";
|
||||
case "boolean":
|
||||
return "Boolean";
|
||||
case "char":
|
||||
return "Character";
|
||||
default:
|
||||
return simple;
|
||||
}
|
||||
}
|
||||
|
||||
private static String simpleJavaType(String javaType) {
|
||||
if (javaType == null) {
|
||||
return "";
|
||||
}
|
||||
String s = javaType.trim();
|
||||
if (s.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
int lt = s.indexOf('<');
|
||||
if (lt > 0) {
|
||||
s = s.substring(0, lt).trim();
|
||||
}
|
||||
int dot = s.lastIndexOf('.');
|
||||
if (dot >= 0 && dot < s.length() - 1) {
|
||||
s = s.substring(dot + 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private Map<String, FieldSchema> fieldsByPath(TypeSchema schema) {
|
||||
Map<String, FieldSchema> result = new LinkedHashMap<>();
|
||||
if (schema == null) {
|
||||
return result;
|
||||
}
|
||||
for (FieldSchema f : schema.getFields().values()) {
|
||||
result.put(f.getPath(), f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, FieldSchema> leaves(TypeSchema schema) {
|
||||
Map<String, FieldSchema> result = new LinkedHashMap<>();
|
||||
if (schema == null) {
|
||||
return result;
|
||||
}
|
||||
for (FieldSchema f : schema.getFields().values()) {
|
||||
if (f.getJsonType() != JsonType.OBJECT && f.getJsonType() != JsonType.ARRAY) {
|
||||
result.put(f.getPath(), f.getJsonType());
|
||||
result.put(f.getPath(), f);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user