簡體   English   中英

如何將 JSON 轉換為 scala shapeless.hlist?

[英]How to convert JSON to scala shapeless.hlist?

我得到了像 {"name":"susan","age":25} 這樣的 json,以及像 "name:String,age:Int" 這樣的 json 鍵集的提示,如何從那個 json 創建一個 HList?

根據您添加然后刪除的代碼,似乎有一個運行時字符串提示"name:String,age:Int"和運行時字符串 json {"name":"susan","age":25} ,您想要獲得一個帶有 運行時反射HList 您可以按如下方式執行此操作

import shapeless.HList
import scala.reflect.runtime
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
val tb = runtime.currentMirror.mkToolBox()

val jsonStr = """{"name":"susan","age":25}"""
val hint = "name:String,age:Int"
val classType = tb.define(tb.parse(s"case class Test($hint)").asInstanceOf[ImplDef]).asClass.toType
val hlist = tb.eval(q"""
  import io.circe.generic.auto._
  import io.circe.parser.decode
  val classInstance = decode[$classType]($jsonStr)

  import shapeless.Generic
  Generic[$classType].to(classInstance.toOption.get)
""").asInstanceOf[HList]
println(hlist) // susan :: 25 :: HNil

請注意,您在運行時執行所有操作,因此您將無法在編譯時訪問String :: Int :: HNil類型,而hlist靜態類型僅為HList (不是String :: Int :: HNil ),而HList實際上並不好不僅僅是List[Any]

生成.sbt

libraryDependencies ++= Seq(
  scalaOrganization.value % "scala-reflect"  % scalaVersion.value,
  scalaOrganization.value % "scala-compiler" % scalaVersion.value,
  "com.chuusai" %% "shapeless" % "2.4.0-M1",
  "io.circe" %% "circe-core"    % "0.13.0",
  "io.circe" %% "circe-parser"  % "0.13.0",
  "io.circe" %% "circe-generic" % "0.13.0"
)

實際上,我想我們做了一些奇怪的事情。 我們使用的是高度的類型級庫(不成形瑟茜目的是靜態類型安全),然后在與反射無視類型安全和實際得到的運行時運行這些List[Any]HList )。

我想如果List[Any] (字段值列表)對你來說足夠了,那么你只需要使用更多的運行時庫。 例如,使用json4s

import org.json4s.{JInt, JObject, JString, JValue}
import org.json4s.jackson.JsonMethods._

val jsonStr: String = """{"name":"susan","age":25}"""
val json: JValue = parse(jsonStr) //JObject(List((name,JString(susan)), (age,JInt(25))))
val l: List[JValue] = json.asInstanceOf[JObject].obj.map(_._2) //List(JString(susan), JInt(25))
val res: List[Any] = l.map {
  case JString(s) => s
  case JInt(n)    => n
} //List(susan, 25)

生成.sbt

libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.9"

其實同樣可以用 Circe 來完成,只是用parse而不是decode[A]

import io.circe.{Json, JsonNumber}
import io.circe.parser.parse

val jsonStr: String = """{"name":"susan","age":25}"""
val json: Json = parse(jsonStr).toOption.get //{"name":"susan","age":25}
val l: List[Json] = json.asObject.get.values.toList //List("susan", 25)
val res: List[Any] = l.map(_.fold[Any](null, null, (_: JsonNumber).toInt.get, identity[String], null, null)) //List(susan, 25)

如果您需要 case 類或元組的實例而不是HList替換

tb.eval(q"""
  import io.circe.generic.auto._
  import io.circe.parser.decode
  val classInstance = decode[$classType]($jsonStr)

  import shapeless.Generic
  Generic[$classType].to(classInstance.toOption.get)
""").asInstanceOf[HList] // susan :: 25 :: HNil

tb.eval(q"""
  import io.circe.generic.auto._
  import io.circe.parser.decode
  decode[$classType]($json).toOption.get
""").asInstanceOf[Product] //Test(susan,25)

或者

tb.eval(q"""
  import io.circe.generic.auto._
  import io.circe.parser.decode
  val classInstance = decode[$classType]($json)

  import shapeless.Generic
  Generic[$classType].to(classInstance.toOption.get).tupled
""").asInstanceOf[Product] //(susan,25)

相應地。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM