2016-10-17 14 views
1

ここでcsv行を解析しようとしていますが、各フィールドは異なるタイプにすることができます。エラーの蓄積を処理するために、私は[String、B]を使用しています。ここで、Stringはエラーメッセージで、Bは値です。ここで問題となるのは、Bは、異なるタイプのOption [Int]、String、Array [String]を使用できるため、結果的にマップを使用できなくするタイプのString(String、Either [String、java.io.Serializable])となります。これらの値を再利用してオブジェクトのプロパティを設定すると同時に、エラーをよりエレガントに累積する方法がありますか(私はそこにいると確信しています)?Scalaの[String、B]を使用してエレガントなエラーを累積する問題

override def parseCsv(implicit fields: Map[String, String]): Either[String, User] = { 

    val parsedValues = Map(Headers.Id -> getFieldAsString(Headers.Id), 
        Headers.FirstName -> getFieldAsString(Headers.FirstName), 
        Headers.LastName -> getFieldAsString(Headers.LastName), 
        Headers.Email -> getFieldAsString(Headers.Email), 
        Headers.TimeZone -> getFieldAsString(Headers.TimeZone), 
        Headers.Region -> getOption(Headers.Region), 
        Headers.Phone -> getOption(Headers.Phone), 
        Headers.ProfileImage -> getFieldAsString(Headers.ProfileImage), 
        Headers.Roles -> getFieldAsArray(Headers.Roles)) 
    val errors = parsedValues.collect { case (key, Left(errors)) => errors } 
    if (!errors.isEmpty) Left(errors.mkString(", ")) 
    else { 
    val user = new User 
    user.id = getFieldAsString(Headers.Id).right.get 
    user.firstName = getFieldAsString(Headers.FirstName).right.get 
    user.lastName = getFieldAsString(Headers.LastName).right.get 
    user.email = getFieldAsString(Headers.Email).right.get 
    user.timeZone = getFieldAsString(Headers.TimeZone).right.get 
    user.phoneNumber = (for { 
          region <- getOption(Headers.Region).right.get 
          phone <- getOption(Headers.Phone).right.get 
          _ = validatePhoneNumber(phone, region) 
         } yield { 
          new PhoneNumber(region, phone) 
         }).orNull 
    user.profileImageUrl = getFieldAsString(Headers.ProfileImage).right.get 
    user.roles = getFieldAsArray(Headers.Roles).right.get 
    Right(user) 
    } 
} 

答えて

1

B Sのすべてのタイプのcase classesを作成します。これらのケースクラスは、共通の特性をいくつか拡張する必要があります。ユーザーオブジェクトにデータを入力するだけで、パターンが一致し、値が取得されます。

sealed trait Result { 
    val paramName: String 
} 

case class OptionInt(override val paramName: String, value: Option[Int]) extends Result 

case class ArrayString(override val paramName: String, value: Array[String]) extends Result 

case class StringValue(override val paramName: String, value: String) extends Result 

今、最終的なタイプは、ファイル全体を解析した後Either[String, Result]

ようになるあなたはOption[Int]firstNameとしてageを期待している場合はStringとしてList[Result]

を作成し、この

list.foreach { result => 
    result match { 
     case Option("age", value) => userId.age = value.getOrElse(defaultAge) 
     case StringValue("firstName", value) => userId.firstName = value 
     case StringValue("email", value) => userId.email = value 
     case _ => //do nothing 
    } 
} 
を行います
関連する問題