如何将JSON转换为scala shapeless.hlist?
我得到了类似于{“name”:“susan”,“age”:25}的json键集提示,以及类似于“name:String,age:Int”的json键集提示,如何从该json创建HList?基于您添加和删除的,似乎有一个运行时字符串提示如何将JSON转换为scala shapeless.hlist?,scala,reflection,apache-flink,shapeless,hlist,Scala,Reflection,Apache Flink,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 impo
“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]
更好
build.sbt
事实上,我想我们做了一些奇怪的事。我们使用高度类型级别的库(,)来实现静态类型安全,然后在运行时运行它们,反射忽略类型安全并获取实际的
List[Any]
(HList
)
我想如果List[Any]
(字段值列表)对您来说足够了,那么您只需要使用一个更具运行时性的库。例如,与
build.sbt
实际上,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
replace
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
与
或
相应地,Shapeless是编译安全的,JSON不是。需要明确的是,没有什么“自动”的方法可以做到(即,你不能做出一些能够神奇地猜测JSON字符串类型的东西)。这里有一个Dave Gurnell的《变形书》(第5章)的简介:我建议你看看任何像circe这样的JSON库。这听起来像是另一个问题。最好用所有细节来扩展这个问题,或者关闭这个问题,打开一个新的问题来吸引更多的注意力。无论如何,我不认识弗林克,所以我再也帮不上忙了,对不起。@LuisMiguelMejíaSuárez“像circe这样的库读取一个json a将它转换成一个HList,然后它可以将它转换成一个case类”一种HList(
String::Int::HNil
)或case类(a
case类a(s:String,I:Int))必须在编译时知道。但是提示“name:String,age:Int”
似乎是一个运行时字符串。
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.9"
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)
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)