簡體   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