如何将JSON转换为scala shapeless.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”:“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]
更好

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)