Scala如何扩展嵌套Case Class元数据并获取Option类型信息?
实现方案
针对你提出的两个需求,完全可以通过Scala反射实现,以下是具体的代码示例:
1. 递归展开嵌套Case Class字段+识别Option类型
我们可以把原有的反射方法改造成递归形式,既支持自动展开嵌套的Case Class字段,也能识别字段是否为Option类型并提取其内部类型:
import scala.reflect.runtime.universe._ case class MyChgClass(b: Option[String], c: Option[String], d: Option[String]) case class MyFullClass(k: Int, b: String, c: String, d: String) case class MyEndClass(id: Int, after: MyFullClass) // 定义字段元数据结构,包含所有需要的信息 case class FieldMeta( fieldName: String, actualType: String, isOption: Boolean, nestedFields: Option[List[FieldMeta]] = None ) def getCaseClassMeta[T: TypeTag]: List[FieldMeta] = { val tpe = typeOf[T] tpe.members.collect { case accessor: MethodSymbol if accessor.isCaseAccessor => val fieldType = accessor.returnType // 判断是否为Option类型 val isOption = fieldType.baseClasses.contains(typeOf[Option[_]].typeSymbol) // 提取实际类型(Option则取内部类型) val realType = if (isOption) { fieldType.typeArgs.head.toString } else { fieldType.toString } // 递归处理嵌套Case Class val nestedMeta = if (fieldType.typeSymbol.isCaseClass) { Some(getCaseClassMeta(fieldType)) } else { None } FieldMeta(accessor.name.toString, realType, isOption, nestedMeta) }.toList.reverse // 反转恢复Case Class定义时的字段顺序 } // 测试嵌套展开 val endClassMeta = getCaseClassMeta[MyEndClass] println(endClassMeta) // 测试Option类型识别 val chgClassMeta = getCaseClassMeta[MyChgClass] println(chgClassMeta)
执行结果
运行代码后会得到如下输出:
List( FieldMeta(id, Int, false, None), FieldMeta(after, MyFullClass, false, Some(List( FieldMeta(k, Int, false, None), FieldMeta(b, String, false, None), FieldMeta(c, String, false, None), FieldMeta(d, String, false, None) ))) ) List( FieldMeta(b, String, true, None), FieldMeta(c, String, true, None), FieldMeta(d, String, true, None) )
核心实现说明
- 嵌套展开:通过
fieldType.typeSymbol.isCaseClass判断字段类型是否为Case Class,若是则递归调用方法获取嵌套字段的元数据。 - Option识别:通过检查字段类型的
baseClasses是否包含Option[_]的类型符号来判定,同时通过typeArgs.head提取Option包裹的实际类型。 - 字段顺序:反射收集的字段默认是逆序的,通过
reverse方法恢复Case Class定义时的原始顺序。
内容的提问来源于stack exchange,提问作者Ged
相关产品推荐
相关产品推荐

