2017-03-01 83 views
1

說我有一個案例類,如:序列化/反序列化對象到/從分隔字符串

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

,這也是存儲在一個文件,其中每行的樣子:

123|"john"|35 

我希望在一個用戶對象和字符串表示之間來回執行此分析。

在Scala中做這件事的最好方法是什麼?

我知道我可以做一個字符串拆分,但想知道如果他們是一個更清潔的方法和更習慣。

+0

要做到這一點正確的方式,你需要寫一個完整的解析器來妥善處理所有情況。 –

+0

使用像https://github.com/tototoshi/scala-csv這樣的庫,並將字段分隔符設置爲'|'字符,然後將每個讀取的行映射到您的案例大小值。 – Yawar

回答

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}""" 

    } 

用法:

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: 實例與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)) 
}