【问题标题】:scala convert String to generic typescala将String转换为泛型
【发布时间】:2013-07-18 12:06:42
【问题描述】:

我正在解析一个 json。我想将它的值转换为其他类型。 即

//json = JSON String 
val seq = net.liftweb.json.parse(json).\\("seq").values.toString.toLong
val userName = net.liftweb.json.parse(json).\\("name").values.toString
val intNum = net.liftweb.json.parse(json).\\("intId").values.toInt

我想使用泛型方法更“scala”的方式来转换它,我尝试了这样的方法:

object Converter{
  def JSONCaster[T](json:String,s:String):T={
    net.liftweb.json.parse(json).\\(s).values.toString.asInstanceOf[T]
  }
}

但出现转换错误:

java.lang.ClassCastException: java.lang.String 无法转换为 java.lang.Long 在 scala.runtime.BoxesRunTime.unboxToLong(未知 来源)

【问题讨论】:

  • 有一系列令人困惑的竞争解决方案(提供解决方案的竞争库)...

标签: scala


【解决方案1】:

我遇到了同样的问题,并记得 Play 框架有一些功能可以做类似的事情。在挖掘了源代码后,我发现了这个Class

基本上,我们可以这样做:

object JSONCaster {

  def fromJson[T](json: String, s: String)(implicit converter: Converter[T]): T = {
    converter.convert(net.liftweb.json.parse(json).\\(s).values.toString)
  }

  trait Converter[T] { self =>
    def convert(v: String): T
  }

  object Converter{
    implicit val longLoader: Converter[Long] = new Converter[Long] {
      def convert(v: String): Long = v.toLong
    }

    implicit val stringLoader: Converter[String] = new Converter[String] {
      def convert(v: String): String = v
    }

    implicit val intLoader: Converter[Int] = new Converter[Int] {
      def convert(v: String): Long = v.toInt
    }

    // Add any other types you want to convert to, even custom types!
  }
}

可以这样称呼:

JSONCaster.fromJson[Long](json, "seq")

缺点是我们必须为我们想要转换的所有类型定义隐式转换器。这样做的好处是使界面真正干净且可重复使用。

【讨论】:

    【解决方案2】:

    查看在 Spray 中实现的 marshalling/unmarshalling。您可能不需要重新发明解决方案,如果需要,您可以查看 their source 了解他们是如何实施的。

    Spray 的编组/解组类似于对象图序列化,并且不仅仅使用 JSON,因此在实现中存在一些额外的固有复杂性。

    您也可以绕过手动解析 JSON 并尝试 lift-json

    lift-json 更接近 JSON,尽管通过 extract 它可以像 Spray 的 marshaller/unmarshaller 一样运行。

    【讨论】:

    • json 只是一个例子。想要在 scalaish 123avi@gmail.com 中将字符串转换为泛型类型
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      这里我在 scala 中有一个通用方法,使用 liftweb/lift-json。 作为一个想法,您需要提供隐式 Manifest。

      import net.liftweb
      
      private def jsonToObjectsSeq[T](jsonAsString: String)(implicit man: Manifest[T]): Seq[T] = {
        parse(jsonAsString)
          .children
          .map(_.extract[T])
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-16
        • 2019-08-18
        • 2020-08-17
        • 2018-10-06
        • 2016-07-21
        • 2016-08-22
        • 2020-06-04
        相关资源
        最近更新 更多