提取具有上限的案例 class

Extracting a case class with an upper bound

我想从 JSON 字符串中提取一个案例 class,并为每个 class 重用代码。 this question 之类的东西会很完美。但这意味着我必须为每个要提取的 class 编写。

我希望做这样的事情:

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 数据,以防 class 像这样:

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

我希望我可以重用 fromJSONtoJSON 只有一次通过上限类型

class TwitterParser extends SocialMonitorParser[TwitterData] {

覆盖来自JSON} classFacebookParser 扩展了 SocialMonitorParser[FacebookData]

非常感谢。

我不确定您为什么希望 SocialMonitorParserabstractSerializable 或者您将如何使用它,但如果您仔细查看错误,您可能会看到编译器想要一个 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")
}

获得完全符合预期的输出。