本文介绍了如何将 JSON 转换为 scala shapeless.hlist?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我得到了像 {"name":"susan","age":25} 这样的 json,以及像 "name:String,age:Int" 这样的 json 键集的提示,如何从那个json?

I got json like {"name":"susan","age":25},and a hint to json keyset like "name:String,age:Int",how to create a HList from that json?

推荐答案

基于您添加然后删除的代码,似乎有一个运行时字符串提示 "name:String,age:Int" 和运行时字符串 json {"name":"susan","age";:25},你想得到一个 HList运行时反射.您可以按以下方式执行此操作

Based on the code you added and then deleted, it seems, having a runtime-string hint "name:String,age:Int" and runtime-string json {"name":"susan","age":25}, you want to get an HList with runtime reflection. You can do this as follows

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 (not String :: Int :: HNil) 和 HList 实际上并不比 List[Any] 好>.

Please notice that you do everything at runtime so you'll have no access to type String :: Int :: HNil at compile time and hlist has static type just HList (not String :: Int :: HNil) and HList is actually not better than just List[Any].

build.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"
)


实际上,我想我们做了一些奇怪的事情.我们使用高度类型级别的库(shapelesscirce) 旨在实现静态类型安全,然后在运行时通过反射运行它们,忽略类型安全并实际获取 List[Any] (HList).


Actually, I guess we do someting strange. We use highly type-level libraries (shapeless, circe) aimed to static type safety and then run them at runtime with reflection ignoring type safety and getting actually List[Any] (HList).

我想如果 List[Any](字段值列表)对你来说足够了,那么你只需要使用更多的运行时库.例如,使用 json4s

I guess that if List[Any] (list of field values) is enough for you then you just need to use a more runtime library. For example, with 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)

build.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)

相应地.

这篇关于如何将 JSON 转换为 scala shapeless.hlist?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 10:17