gpt4 book ai didi

json - 获取案例类的具体类型

转载 作者:行者123 更新时间:2023-12-01 12:54:29 24 4
gpt4 key购买 nike

我有这个:

sealed trait Block

sealed case class Header(param1: String,
param2: String,
...) extends Block

...
(more sealed case classes that follows the same pattern)

稍后,我将这些 block 分组到一个 Seq 中,如下所示:

val blocks: Seq[Block with Product with Serializable] = Seq(structure.header, structure.body, ...)

我想将每个 block 序列化为 Json(使用 Play)。我正在这样做:

blocks.map{
x =>
serializeBlock(x)
}

“serializeBlock”的定义:

def serializeBlock[A<:Block](block:A): String = {
block match {
case block: Header => Json.toJson(block).toString()
case block: Body => Json.toJson(block).toString()
... n-times for every possible case class that mixes the block trait
}
}

对于每个具体 block (标题、正文...),我都有读者和作者,但是,如您所见,当我在 Seq Scala 中混合这些 block 时,将其视为通用类型 block ,因此我正在做与每种可能的 block 类型匹配的模式(隐式转换?)。如果我只是在 Map Play 中调用“Json.toJson”,就会提示找不到“ block ”类型的读取器/写入器。

“ block ”是一个相对较大的 JSON 的片段。我正在获取 JSON,将其拆分为合格的“ block ”,然后将其作为字符串保存在数据库中:

“大”JSON:

{
"header" : {
"param1" : "",
...
},
"body" : {
"param1" : "",
...
}
...
}

block

{
"param1" : "",
...
}

我的问题是:有没有什么方法可以在不重复 n 次“block: type”模式的情况下进行序列化?我的意思是:有什么方法可以获取该 block 的具体类型(知道 Seq 被键入为父类(super class)“ block ”而不是该 block 的“具体”类型)?

编辑

我对每个 block 都有一个读取器/写入器,如下所示:

implicit val headerReader: Reads[Header] = (
(JsPath \ "param1").read[String] and
(JsPath \ "param2").read[String] and
...
)(Header.apply _)

implicit val headerWriter: Writes[Header] = (
(JsPath \ "param1").write[String] and
(JsPath \ "param2").write[String] and
...
)(unlift(Header.unapply))

编辑 2:

Shapeless解决这个问题的方法?

编辑 3:

正如 Andrzej Jozwik 所指出的:“param1”和“param2”是我用来定义我的 JSON 结构的“通配符”参数。每个 block 都有不同的参数。

最佳答案

shapeless' HList 对您来说似乎是一个可能的解决方案。这是一个看起来非常接近您想要执行的操作的示例:

import shapeless._

sealed trait Block
case class Test1(a: String, b: String) extends Block
object Test1 {
implicit val writes = (
(JsPath \ "a").write[String] and
(JsPath \ "b").write[String]
)(unlift(Test1.unapply))
}

case class Test2(c: String, d: String) extends Block
object Test2 {
implicit val writes =(
(JsPath \ "c").write[String] and
(JsPath \ "d").write[String]
)(unlift(Test2.unapply))
}

object serializeBlock extends Poly1 {
implicit def default[T <: Block](implicit w: Writes[T]) = at[T] { x =>
Json.toJson(x).toString
}
}

val blocks = Test1("hi", "hello") :: Test2("what", "why") :: HNil

blocks.map(serializeBlock).toList // List[String]({"a": "hi", "b": "hello"}, {"c": "what", "d": "why"})

请注意,HList 的每个成员都必须具有可用于该类型的隐式 Writes。如果不是这样,您得到的错误就没有太大帮助:

val list = Test1("hi", "hello") :: Test2("a", "b") :: NoWrites("wrong") :: HNil
list.map(serializeBlock)

错误:

could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[serializeBlock.type,shapeless.::[Test1,shapeless.::[Test2,shapeless.::[NoWrites,shapeless.HNil]]]]

这只是意味着不可能为您在其上调用 map 的 HList 的某些成员调用 serializeBlock。

在这种情况下,它无法在 NoWrites 对象上调用 serializeBlock,因为在当前范围内没有可用的隐式 Writes[NoWrites]。

如果 HList 中的任何对象没有扩展 Block,您将得到类似的错误。

关于json - 获取案例类的具体类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31946969/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com