修剪案例类的String字段的值

obl*_*ion 7 scala shapeless

我正在编写一个使用无形的泛型函数,它接受a的实例case class并修剪字符串的所有字段值.案例类可以有可选字段,嵌套对象,列表等.

我有一个案例课Person.

case class Person(name: Option[String], address: List[String], friends: List[Person])
Run Code Online (Sandbox Code Playgroud)

我目前拥有的功能:

import shapeless._, ops.hlist._

  object trimmer extends Poly1 {
    implicit val stringOptCase = at[Option[String]](_.map(_.trim))
    implicit val stringListCase = at[List[String]](_.map(_.trim))
    implicit def skipCase[A] = at[A](identity)
  }

  def trimStringValues[A, R <: HList](a: A)(implicit
                                     gen: Generic.Aux[A, R],
                                     mapper: Mapper.Aux[trimmer.type, R, R]
  ) = gen.from(mapper(gen.to(a)))
Run Code Online (Sandbox Code Playgroud)

当我使用上面的函数时,它只适用于类的根级别name字段Person.它不适用于列表或对象字段.

val person = Person(name = Some(" john "), address = List(" ny"," vegas "), friends = List(Person(Some(" alicia"), List(" peter"), Nil)))

trimStringValues(person) // Person(Some(john),List(ny, vegas),List(Person(Some( alicia),List( peter),List())))
Run Code Online (Sandbox Code Playgroud)

我怎么解决这个问题?

Tra*_*own 5

首先,它似乎在您的评论输出中address以及name预期的效果上都在工作。它不工作friends,因为List[Person]比赛的skipCase情况下,它是既非Option[String]List[String]

解决此问题的最简单方法是使用Shapeless的everywhere合并器。鉴于以上代码,您可以编写以下代码:

scala> shapeless.everywhere(trimmer)(person)
res1: Person = Person(Some(john),List(ny, vegas),List(Person(Some(alicia),List(peter),List())))
Run Code Online (Sandbox Code Playgroud)

实际上,您可以通过更简单的trimmer实现来完成同一件事:

object trimStrings extends Poly1 {
  implicit val stringCase: Case.Aux[String, String] = at[String](_.trim)
}
Run Code Online (Sandbox Code Playgroud)

或者等效地,但更简洁地:

import shapeless.poly.->

object trimStrings extends (String -> String)(_.trim)
Run Code Online (Sandbox Code Playgroud)

然后:

scala> shapeless.everywhere(trimStrings)(person)
res5: Person = Person(Some(john),List(ny, vegas),List(Person(Some(alicia),List(peter),List())))
Run Code Online (Sandbox Code Playgroud)

如果要精确控制要修剪的字符串,则可以返回到原始实现,并添加显式List[Person]大小写,或者添加更通用的大小写,以匹配此类类型并trimmer递归应用。但是,既然您说要修剪所有字符串,那everywhere听起来就是您想要的。