Scala使用反射检查至少一个案例类字段值是否为非空

gui*_*ebl 1 reflection validation scala optional case-class

我有一个要求,对于具有大约30+个给定案例类的Option [T]字段,必须至少具有1个字段nonEmpty才有效。我没有单独检查每个字段,而是选择了以通用方式通过反射检查所有字段。我想出的代码(也基于SO中的其他答案)是:

import scala.reflect.runtime.universe._
import scala.reflect.runtime.{universe => ru}

  // gets all methods of a Case Class
  def getMethods[T: ru.TypeTag] = typeOf[T].members.collect {
    case m: MethodSymbol if m.isCaseAccessor => m
  }.toList


  /**
    *  Returns the value of all Case Class fields
    * @param obj case class object
    * @return a Sequence of all field values
    */
  def getAllCaseClassFieldValues[T: ru.TypeTag](obj: Object): Seq[Any] = {
    val mirror = ru.runtimeMirror(getClass.getClassLoader)
    getMethods[T].map(m => mirror.reflect(obj).reflectField(m).get)
  }
Run Code Online (Sandbox Code Playgroud)

案例类:

case class SampleRequest(field1: Option[String], field2: Option[String], //.... up to 30 or more fields
Run Code Online (Sandbox Code Playgroud)

检查至少1是否为nonEmpty的代码:

 val fieldValues = getAllCaseClassFieldValues[SampleRequest](r)
 val noneCount = fieldValues.count(_ == None)
 val atLeastOneNonEmpty = noneCount < fieldValues.size
Run Code Online (Sandbox Code Playgroud)

我想知道是否会有更好的方法通过反射或其他机制进行验证?

Gra*_*ath 5

这是一个案例类,因此它实现了Product特质。产品特征具有迭代器def productIterator : Iterator[Any]

case class Foo(one: Option[Int], two: Option[String], three : Option[Double])

var i = Foo(None, Some("Woot!"), None)
var j = Foo(Some(1), Some("There Can Be Only"), None)
var k = Foo(None, None, None)

i.productIterator.exists(_.isInstanceOf[Some[_]]) // True
j.productIterator.exists(_.isInstanceOf[Some[_]]) // True
k.productIterator.exists(_.isInstanceOf[Some[_]]) // False
Run Code Online (Sandbox Code Playgroud)

在评估稀疏填充的流数据时,我一直使用此技巧。