Как получить карту имен полей с типами полей класса case с бесформенным
Я просмотрел почти все учебные пособия и у меня на столе есть "Астронавты типов", но я до сих пор не могу понять, как написать фрагмент кода, который может извлекать карту имен для типов, используя бесформенный класс case. Чтобы быть точным, я после следующего интерфейса:
case class Sample(id: String, date: LocalDate)
def sampleExpectedMetadata = expectedMetadata[Sample] // = ("id" -> "String", "date" -> "LocalDate")
def expectedMetadata[T]: Map[String, String] = ???
Буду признателен за помощь любого, кто может помочь с написанием правильной реализации.
2 ответа
Вы имели в виду что-то подобное?
import shapeless._
import shapeless.record._
import shapeless.labelled._
object expectedMetadata {
def apply[T](implicit g: GetFieldTypes[T]): Map[String, String] = g.getFieldTypes
sealed trait GetFieldTypes[T] {
def getFieldTypes: Map[String,String]
}
implicit val hnil = new GetFieldTypes[HNil] {
def getFieldTypes = Map.empty
}
implicit def hcons[K <: Symbol, V, T <: HList](implicit
wit: Witness.Aux[K],
typ: Typeable[V],
rest: GetFieldTypes[T]
) = new GetFieldTypes[FieldType[K, V] :: T] {
def getFieldTypes = rest.getFieldTypes + (wit.value.name -> typ.describe)
}
implicit def caseClass[T, G](implicit
lg: LabelledGeneric.Aux[T, G],
rest: GetFieldTypes[G]
) = new GetFieldTypes[T] {
def getFieldTypes = rest.getFieldTypes
}
}
Образец использования:
scala> case class Sample(id: String, date: LocalDate)
scala> expectedMetadata[Sample]
res1: Map[String,String] = Map(date -> LocalDate, id -> String)
Я могу ошибаться, что Shapeless не будет иметь ничего общего с такого рода самоанализом. Если использовать ответ из списка "Получить имена полей из класса case" и уточнить его, ваш ответ будет следующим:
import scala.reflect.runtime.universe._
def expectedMetadata[T](implicit t:TypeTag[T]):Map[String, String] =
t.tpe.members
.collect { case m:MethodSymbol if m.isCaseAccessor => m }
.map(x => x.name.toString -> x.returnType.toString)
.toMap
Куда, expectedMetadata[Sample]
вернусь Map[String,String] = Map(date -> java.time.LocalDate, id -> String)