繁体   English   中英

Scala - 如何使用 ToolBox 创建的动态案例 class 提取 Json4s

[英]Scala - How to extract Json4s with dynamic case class created with ToolBox

我使用工具箱动态定义了案例 class。 当我提取 json4s 时,我得到以下异常:

  import org.json4s._
  import scala.reflect.runtime._
  import scala.tools.reflect.ToolBox

  implicit val formats = DefaultFormats

  val cm = universe.runtimeMirror(getClass.getClassLoader)
  val toolBox = cm.mkToolBox()

  val parse =
    toolBox.parse(
      s"""
         | case class Person( name:String, age:String)
         | scala.reflect.classTag[ Person].runtimeClass
       """.stripMargin)

  val person = toolBox.compile( parse)().asInstanceOf[Class[_]]

  val js = JsonMethods.parse("""{ "name":"Tom","age" : "28"}""")
  val jv = js.extract[person.type ] //How do I pass the class type?

**"Exception in thread "main" org.json4s.MappingException: No constructor for type Class, JObject(List((name,JString(Tom)), (age,JString(28))))"** 

但是在创建动态创建的 class 的虚拟实例之后,然后传入该虚拟 class 的类型,它将被解析。

我不知道为什么。 如何在不创建虚拟实例的情况下进行解析?

  import org.json4s._
  import scala.reflect.runtime._
  import scala.tools.reflect.ToolBox

  implicit val formats = DefaultFormats

  val cm = universe.runtimeMirror(getClass.getClassLoader)
  val toolBox = cm.mkToolBox()

  val parse =
    toolBox.parse(
      s"""
         | case class Person( name:String, age:String)
         | scala.reflect.classTag[ Person].runtimeClass
       """.stripMargin)

  val person = toolBox.compile( parse)().asInstanceOf[Class[_]]
  val dummy  = person.getConstructors.head.newInstance( "a", "b") //make dummy instance

  val js = JsonMethods.parse("""{ "name":"Tom","age" : "28"}""")
  println( js.extract[ dummy.type ] ) // Result: Person(Tom,28)

x.type是 singleton 类型。 所以person.type不可能是正确的,它是这个特定变量val person: Class[_]的 singleton 类型。

幸运的是,由于运行时反射, dummy.type是正确的。 这甚至适用于普通情况 class

import org.json4s._
import org.json4s.jackson.JsonMethods

implicit val formats = DefaultFormats

case class Person(name: String, age: String)

val js = JsonMethods.parse("""{ "name":"Tom","age" : "28"}""")

val dummy0: AnyRef = Person("a", "b")
val dummy: AnyRef = dummy0

js.extract[dummy.type] // Person(Tom,28)

实际上在解决隐含之后js.extract[Person]

js.extract[Person](formats, ManifestFactory.classType(classOf[Person])

js.extract[dummy.type]

js.extract[dummy.type](formats, ManifestFactory.singleType(dummy))

因此,对于工具箱生成的案例 class 我们可以尝试

import org.json4s._
import org.json4s.jackson.JsonMethods
import scala.reflect.ManifestFactory
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val cm = universe.runtimeMirror(getClass.getClassLoader)
val toolBox = cm.mkToolBox()

implicit val formats = DefaultFormats

val person = toolBox.eval(q"""
  case class Person(name:String, age:String)
  scala.reflect.classTag[Person].runtimeClass
""").asInstanceOf[Class[_]]

val js = JsonMethods.parse("""{ "name":"Tom","age" : "28"}""")

js.extract(formats, ManifestFactory.classType(person))
// java.lang.ClassCastException: __wrapper$1$6246735221dc4d64a9e372a9d0891e5e.__wrapper$1$6246735221dc4d64a9e372a9d0891e5e$Person$1 cannot be cast to scala.runtime.Nothing$

toolBox.eval(tree)代替toolBox.compile(toolBox.parse(string))()

但这不起作用。

清单应从工具箱编译时捕获

import org.json4s._
import org.json4s.jackson.JsonMethods
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val cm = universe.runtimeMirror(getClass.getClassLoader)
val toolBox = cm.mkToolBox()

implicit val formats = DefaultFormats

val person = toolBox.eval(q"""
  case class Person(name:String, age:String)
  val clazz = scala.reflect.classTag[Person].runtimeClass
  scala.reflect.ManifestFactory.classType(clazz)
""").asInstanceOf[Manifest[_]]

val js = JsonMethods.parse("""{ "name":"Tom","age" : "28"}""")

js.extract(formats, person) // Person(Tom,28)

或者,您根本不需要 java-reflection Class 你可以做

import scala.reflect.runtime
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

val cm = runtime.currentMirror
val toolBox = cm.mkToolBox()

toolBox.eval(q"""
  import org.json4s._
  import org.json4s.jackson.JsonMethods

  implicit val formats = DefaultFormats

  case class Person(name: String, age: String)

  val js = JsonMethods.parse(${"""{"name":"Tom","age" : "28"}"""})

  js.extract[Person]
""") // Person(Tom,28)

或者

import org.json4s._
import org.json4s.jackson.JsonMethods
import scala.reflect.runtime
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox

object Main extends App {
  val cm = runtime.currentMirror
  val toolBox = cm.mkToolBox()

  implicit val formats = DefaultFormats

  val person: ClassSymbol = toolBox.define(q"case class Person(name: String, age: String)")

  val js = JsonMethods.parse("""{"name":"Tom","age" : "28"}""")

  val jv = toolBox.eval(q"""
    import Main._
    js.extract[$person]
  """)
 
  println(jv)  // Person(Tom,28)
} 

暂无
暂无

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

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