Я пытаюсь рекурсивно перечислить пустые поля с помощью Shapeless. Но, похоже, не отображаются все поля:
https://scastie.scala-lang.org/PtLdSRC2Qfipu054Hzerrw
import shapeless._
import shapeless.labelled.FieldType
trait NullFields[T] {
def apply(value: T, parent: String): Seq[String]
}
object NullFields extends NullFieldsLowPriority {
implicit lazy val hNil = new NullFields[HNil] {
override def apply(value: HNil, parent: String) = Seq.empty
}
implicit def hConsOption[K <: Symbol, V, TailFields <: HList](implicit
witness: Witness.Aux[K],
tailNullFields: NullFields[TailFields]
) = new NullFields[FieldType[K, Option[V]] :: TailFields] {
override def apply(
params: FieldType[K, Option[V]] :: TailFields,
parent: String
) =
(if (params.head.isEmpty) Seq(parent + witness.value.name)
else Seq.empty) ++
tailNullFields(params.tail, parent)
}
implicit def hConsCaseClass[
K <: Symbol,
CC <: Product,
Fields <: HList,
TailFields <: HList
](implicit
generic: LabelledGeneric.Aux[CC, Fields],
nullFields: NullFields[Fields],
witness: Witness.Aux[K],
tailNullFields: NullFields[TailFields]
) = new NullFields[FieldType[K, CC] :: TailFields] {
override def apply(params: FieldType[K, CC] :: TailFields, parent: String) =
nullFields(generic.to(params.head), s"$parent${witness.value.name}.") ++
tailNullFields(params.tail, parent)
}
implicit def caseClass[CC, Fields <: HList](implicit
generic: LabelledGeneric.Aux[CC, Fields],
nullFields: NullFields[Fields]
) = new NullFields[CC] {
override def apply(value: CC, parent: String) =
nullFields(generic.to(value), parent)
}
}
trait NullFieldsLowPriority {
implicit def hConsDefault[K <: Symbol, V, TailFields <: HList](implicit
tailNullFields: NullFields[TailFields]
) = new NullFields[FieldType[K, V] :: TailFields] {
override def apply(params: FieldType[K, V] :: TailFields, parent: String) =
tailNullFields(params.tail, parent)
}
}
case class B(
balba: Int = 0,
profile_experience_desc: Option[String] = None,
vmaf: Va
)
case class Va(
tw_segment: Option[Double],
i20_segment: Option[Double],
ttq_segment: Option[Int]
)
println(implicitly[NullFields[B]].apply(B(vmaf = Va(None, None, None)), ""))
Я не уверен, что это именно то, что вы хотите, но я надеюсь, что вы сможете настроить его так, чтобы он работал в соответствии с вашими потребностями. Я рассматривал следующее как null
s:
None
null
null
s или None
s найдены в классах case и/или Option
sВы можете добавить дополнительные имплициты для обработки других случаев:
import shapeless._
import shapeless.labelled.FieldType
trait NullFields[T] {
def apply(value: T, parent: String): Seq[String]
}
object NullFields extends LowPrioriyImplicits {
def apply[A](implicit nullFields: NullFields[A]): NullFields[A] = nullFields
implicit class NullFieldsOps[A](a: A) {
def nulls(implicit ev: NullFields[A]) = NullFields[A].apply(a, "")
}
implicit def option[V](implicit nullFields: NullFields[V]): NullFields[Option[V]] =
(option: Option[V], parent: String) =>
if (option.isEmpty) Seq(parent)
else nullFields(option.head, parent)
implicit def caseClass[CC, Fields <: HList](implicit
generic: LabelledGeneric.Aux[CC, Fields],
nullFields: NullFields[Fields]
): NullFields[CC] = (value: CC, parent: String) => nullFields(generic.to(value), parent)
implicit def hCons[K <: Symbol, Field, TailFields <: HList](implicit
witness: Witness.Aux[K],
nullFields: Lazy[NullFields[Field]],
tailNullFields: Lazy[NullFields[TailFields]]
): NullFields[FieldType[K, Field] :: TailFields] =
(params: FieldType[K, Field] :: TailFields, parent: String) =>
nullFields.value(params.head, (if (parent.isEmpty) "" else s"$parent.") + witness.value.name) ++
tailNullFields.value(params.tail, parent)
implicit val hNil: NullFields[HNil] = (value: HNil, parent: String) => Seq.empty
}
trait LowPrioriyImplicits {
implicit def other[A]: NullFields[A] =
(value: A, parent: String) => if (value == null) Seq(parent) else Seq.empty
}
Скасти ссылка для того же
@Джоан, Нп. Рад, что помогло. Я снова отредактировал его, чтобы придать классу знакомый вид. Вы можете проверить ссылку Scastie, которая предоставляет класс операций, который может удовлетворить ваши потребности.
Спасибо! Улучшил его еще больше, заменив instance
на тип SAM и неявное преобразование на implicit class
Чёрт возьми! Большое спасибо! Я отредактировал, чтобы соответствовать именно тому, что я искал. Спасибо еще раз!