Как получить карту имен полей с типами полей класса 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)

Другие вопросы по тегам