使用上限提取案例类

时间:2018-01-28 18:26:17

标签: json scala lift

我想从JSON字符串中提取案例类,并为每个类重用代码。 像this question这样的东西本来就很完美。但这意味着我必须为我想要提取的每个类写作。

我希望做类似的事情:

abstract class SocialMonitorParser[C <: SocialMonitorData] extends Serializable {

  def toJSON(socialMonitorData: C): String = {
    Requirements.notNull(socialMonitorData, "This field cannot be NULL!")
    implicit val formats = DefaultFormats
    write(socialMonitorData)
  }

  def fromJSON(json: String): Option[C] = {
    implicit val formats = DefaultFormats // Brings in default date formats etc.
    val jsonObj = liftweb.json.parse(json)

    try {
      val socialData = jsonObj.extract[C]
      Some(socialData)
    } catch {
      case e: Exception => {
        Logger.get(this.getClass.getName).warn("Unable to parse the following JSON:\n" + json + "\nException:\n" + e.toString())
        None
      }
    }
  }

}

但它给了我以下错误:

Error:(43, 39) No Manifest available for C.
val socialData = jsonObj.extract[C]
Error:(43, 39) not enough arguments for method extract: (implicit formats: net.liftweb.json.Formats, implicit mf: scala.reflect.Manifest[C])C.
Unspecified value parameter mf.
val socialData = jsonObj.extract[C]

我希望我可以做这样的事情,也许还有办法。但我无法绕过这个。

我将尝试用其他一些信息来扩展问题。假设我有Twitter和Facebook数据,如下所示:

case class FacebookData(raw_data: String, id: String, social: String) extends SocialMonitorData
case class TwitterData(...) extends SocialMonitorData{ ...}

我希望只要通过上限类型就可以重复使用fromJSONtoJSON

class TwitterParser extends SocialMonitorParser[TwitterData] {

覆盖FromJSON}     FacebookParser类扩展了SocialMonitorParser [FacebookData]

很有责任。

1 个答案:

答案 0 :(得分:0)

我不确定您为什么要SocialMonitorParser abstractSerializable或者您将如何使用它?但如果您仔细观察错误,您可能会看到编译器需要Manifest CManifest是一种Scala方法,通过JVM对泛型强制执行的类型擦除来保存类型信息。如果你解决了这个问题,那么像这样的代码会编译:

import net.liftweb.json._
import net.liftweb.json.Serialization._

trait SocialMonitorData

case class FacebookData(raw_data: String, id: String, social: String) extends SocialMonitorData


class SocialMonitorParser[C <: SocialMonitorData : Manifest] extends Serializable {

  def toJSON(socialMonitorData: C): String = {
    // Requirements.notNull(socialMonitorData, "This field cannot be NULL!")
    implicit val formats = DefaultFormats
    write(socialMonitorData)
  }

  def fromJSON(json: String): Option[C] = {
    implicit val formats = DefaultFormats // Brings in default date formats etc.
    val jsonObj = parse(json)

    try {
      val socialData = jsonObj.extract[C]
      Some(socialData)
    } catch {
      case e: Exception => {
        // Logger.get(this.getClass.getName).warn("Unable to parse the following JSON:\n" + json + "\nException:\n" + e.toString())
        None
      }
    }
  }
}

您可以将其用作

def test(): Unit = {
  val parser = new SocialMonitorParser[FacebookData]

  val src = FacebookData("fb_raw_data", "fb_id", "fb_social")
  println(s"src = $src")

  val json = parser.toJSON(src)
  println(s"json = $json")

  val back = parser.fromJSON(json)
  println(s"back = $back")
}

以完全按照预期获得输出。