简体   繁体   English

提取具有上限的案例类

[英]Extracting a case class with an upper bound

I want to extract a case class from a JSON String, and reuse the code for every class. 我想从JSON字符串中提取案例类,并为每个类重用代码。 Something like this question would have been perfect. 这样的问题将是完美的。 But this means that I have to write for every class I want to extract. 但这意味着我必须为要提取的每个类编写代码。

I was hoping to do something like: 我希望做这样的事情:

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

}

But it gives me the following error: 但这给了我以下错误:

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]

I was hoping I could do something like this, and maybe there is a way. 我希望我可以做这样的事情,也许有办法。 But I can't wrap my head around this. 但是我无法解决这个问题。

I will try to extend the question with some other information. 我将尝试用其他一些信息来扩展这个问题。 Supposing I have Twitter and Facebook data, in case class like these: 假设我有Twitter和Facebook数据,以防此类情况:

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

I wish I could reuse the fromJSON and toJSON just once passing the Upper Bound type 我希望一旦通过Upper Bound类型,就可以重用fromJSONtoJSON

class TwitterParser extends SocialMonitorParser[TwitterData] {

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

Much obliged. 多谢。

I'm not sure why you want SocialMonitorParser to be abstract or Serializable or how are you going to use it but if you look closer at the error you may see that the compilers wants a Manifest for C . 我不确定为什么要让SocialMonitorParserabstract或可Serializable或者您将如何使用它,但是如果您仔细观察该错误,您可能会看到编译器想要CManifest Manifest is a Scala way to preserve type information through the type erasure enforced onto generics by JVM. Manifest是Scala通过JVM强制对泛型强制执行的类型擦除来保留类型信息的一种方式。 And if you fix that, then the code like this compiles: 如果您修复了该错误,则将编译如下代码:

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

and you can use it as 您可以将其用作

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

to get the output exactly as one would expect. 获得与预期完全一样的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM