2017-03-01 4 views
1

Sagen, ich habe einen Fall, Klasse wie:Serialize/Deserialize Objekt zu/von Delimited String

case class User(id: Int, name: String, age: Int) 

Und dies auch in einer Datei gespeichert werden, wobei jede Zeile wie folgt aussieht:

123|"john"|35 

I Ich möchte dieses Parsing zwischen einem User-Objekt und der String-Repräsentation an einem einzigen Ort durchführen.

Was ist der beste Weg, dies in Scala zu tun?

Ich weiß, ich kann nur einen String Split machen, aber ich frage mich, ob sie eine sauberere Herangehensweise und mehr idiomatisch sind.

+0

dies der richtige Weg zu tun, müssen Sie würde einen ganzen Parser schreiben, um ordnungsgemäß zu behandeln alle Fälle. –

+0

Verwenden Sie eine Bibliothek wie https://github.com/tototoshi/scala-csv und setzen Sie das Feldtrennzeichen auf '|' Zeichen, dann ordnen Sie jede gelesene Zeile in Ihre Fallwerte ein. – Yawar

Antwort

3
/** 
    * Serialization/deserialization API 
    */  
    trait Codec[T] { 
    def parse(str: String):Option[T] 

    def write(u: T): String 

    implicit def string2type(str: String):Option[T] = parse(str) 

    implicit def type2string(u: T):String = write(u) 

    implicit def iterable2type(it: Iterable[String]):Iterable[T] = 
     it.flatMap(string2type) 

    } 

    /** 
    * Serialization/deserialization implementation for User 
    */ 
    object UserCodec extends Codec[User] { 
    val pattern = """(\d+)\|"([\w\s]+)"\|(\d+)""".r 

    override def parse(str: String):Option[User] = str match { 
     case pattern(id, name, age) => Some(User(id.toInt, name, age.toInt)) 
     case _ => None 
    } 

    override def write(u: User): String = s"""${u.id}|"${u.name}"|${u.age}""" 

    } 

Verbrauch:

def main(args: Array[String]): Unit = { 
    import UserCodec._ 

    val str = """123|"john asd"|35""" 

    val u:Option[User] = str 
    val s:String = User(1, "a", 1) 

    println(u) // out: Some(User(123,john asd,35)) 
    println(s) // out: 1|"a"|1 
} 

Upd: Beispiel mit Iterables:

def main(args: Array[String]): Unit = { 
    import UserCodec._ 

    val lines = Seq(
     """1|"john"|34""", 
     """2|"bill"|35""", 
     """3|"aaa"|36""" 
    ) 

    val validUsers: Iterable[User] = lines 

    println(validUsers.toList) 
    //out:List(User(1,john,34), User(2,bill,35), User(3,aaa,36)) 
}