如何将JSON转换为Scala shapeless.hlist?

问题描述

我得到了像{“ name”:“ susan”,“ age”:25}这样的json,并提示了json键集,例如“ name:String,age:Int”,如何从该json创建HList? / p>

解决方法

基于您添加并删除的code,看来,您有一个运行时字符串提示"name:String,age:Int"和运行时字符串json {"name":"susan","age":25},就想获得一个{{1 }}和runtime reflection。您可以按照以下步骤进行操作

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好。

build.sbt

List[Any]

实际上,我猜我们有些奇怪。我们使用针对静态类型安全性的高度类型级别的库(shapelesscirce),然后在运行时运行它们,并使用反射忽略类型安全性并实际上获得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(字段值列表)足以满足您的需要,那么您只需要使用更多的运行时库即可。例如,使用json4s

List[Any]

build.sbt

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)

实际上,使用Circe可以做到这一点,只是用libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.9" 而不是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)) //List(susan,25) 替换

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)

相应地。