提取具有上限的案例 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{ ...}
我希望我可以重用 fromJSON
和 toJSON
只有一次通过上限类型
class TwitterParser extends SocialMonitorParser[TwitterData] {
覆盖来自JSON}
classFacebookParser 扩展了 SocialMonitorParser[FacebookData]
非常感谢。
我不确定您为什么希望 SocialMonitorParser
为 abstract
或 Serializable
或者您将如何使用它,但如果您仔细查看错误,您可能会看到编译器想要一个 Manifest
用于 C
。 Manifest
是一种 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")
}
获得完全符合预期的输出。
我想从 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{ ...}
我希望我可以重用 fromJSON
和 toJSON
只有一次通过上限类型
class TwitterParser extends SocialMonitorParser[TwitterData] {
覆盖来自JSON} classFacebookParser 扩展了 SocialMonitorParser[FacebookData]
非常感谢。
我不确定您为什么希望 SocialMonitorParser
为 abstract
或 Serializable
或者您将如何使用它,但如果您仔细查看错误,您可能会看到编译器想要一个 Manifest
用于 C
。 Manifest
是一种 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")
}
获得完全符合预期的输出。