【问题标题】:Serialize / Deserialize Object To/From Delimited String序列化/反序列化对象到/从分隔字符串
【发布时间】:2017-03-01 15:40:32
【问题描述】:

假设我有一个类似的案例类:

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

这也存储在一个文件中,其中每一行如下所示:

123|"john"|35

我想在一个地方在用户对象和字符串表示之间来回执行这种解析。

在 Scala 中最好的方法是什么?

我知道我可以只做一个字符串拆分,但想知道他们是否是一种更清洁的方法和更惯用的方法。

【问题讨论】:

  • 要以正确的方式执行此操作,您需要编写一个完整的解析器来正确处理所有情况。
  • 使用像github.com/tototoshi/scala-csv 这样的库并将字段分隔符设置为“|”字符,然后将每个读取的行映射到您的案例值。

标签: scala csv serialization


【解决方案1】:
  /**
   * 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
}

更新: 带有可迭代对象的示例:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2020-10-19
    相关资源
    最近更新 更多