如何在 Scala 中使用 Circe 解码 JSON Lists/Arrays
How to Use Circe for Decoding JSON Lists/Arrays in Scala
我有代码片段
cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]
其中 Clip 是字符串和数字的简单情况 class。传入的 Json 应该包含一个 json 对象 "playlist" 和一个 "items" 数组,其中每个项目都是一个剪辑。所以 json 应该看起来像
{
"playlist": {
"name": "Sample Playlist",
"items": [
{
"clipId":"xyz",
"name":"abc"
},
{
"clipId":"pqr",
"name":"def"
}
]
}
}
使用上面的代码片段,我遇到了编译错误:
Error:(147, 81) could not find implicit value for parameter d:
io.circe.Decoder[List[com.packagename.model.Clip]]
cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]
我做错了什么?如何使用 circe 为 list/array 个简单项目设置解码?
Circe 正在为 List[Clip]
寻找隐式声明的解码器,但找不到。
我怀疑您没有手动或(半)自动定义解码器。您可以按照官方文档 https://circe.github.io/circe/codec.html.
来完成这两项操作
不幸的是,我无法提供比这更详细的信息,因为这个问题相当模糊。当提供更多详细信息时,我会更新我的答案。
感谢您的帮助。在离开一段时间并以新的眼光回来后,我能够弄明白。
我认为我使用 downArray 函数出错了。
我的解决方案是执行以下操作:
override def main(args: Array[String]): Unit = {
import ClipCodec.decodeClip
val json = parse(Source.fromFile("playlist.json").mkString).right.get
val clips = json.hcursor.downField("params").downField("playlist")
.downField("items").as[Seq[Clip]]
}
为了完整起见,您可以创建一个自定义解码器,在其处理中包含导航,而不是导航到 JSON 值然后解码剪辑:
import io.circe.Decoder, io.circe.generic.auto._
case class Clip(clipId: String, name: String)
val decodeClipsParam = Decoder[List[Clip]].prepare(
_.downField("params").downField("playlist").downField("items")
)
然后如果你有这个:
val json = """{ "params": {
"playlist": {
"name": "Sample Playlist",
"items": [
{
"clipId":"xyz",
"name":"abc"
},
{
"clipId":"pqr",
"name":"def"
}
]
}
}}"""
你可以这样使用解码器:
scala> io.circe.parser.decode(json)(decodeClipsParam)
res3: Either[io.circe.Error,List[Clip]] = Right(List(Clip(xyz,abc), Clip(pqr,def)))
我可能会更进一步,使用自定义案例 class:
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder
case class Clip(clipId: String, name: String)
case class PlaylistParam(name: String, items: List[Clip])
object PlaylistParam {
implicit val decodePlaylistParam: Decoder[PlaylistParam] =
deriveDecoder[PlaylistParam].prepare(
_.downField("params").downField("playlist")
)
}
现在你可以这样写:
scala> io.circe.parser.decode[PlaylistParam](json).foreach(println)
PlaylistParam(Sample Playlist,List(Clip(xyz,abc), Clip(pqr,def)))
不过,您想如何拆分导航和解码主要是个人喜好问题。
我有代码片段
cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]
其中 Clip 是字符串和数字的简单情况 class。传入的 Json 应该包含一个 json 对象 "playlist" 和一个 "items" 数组,其中每个项目都是一个剪辑。所以 json 应该看起来像
{
"playlist": {
"name": "Sample Playlist",
"items": [
{
"clipId":"xyz",
"name":"abc"
},
{
"clipId":"pqr",
"name":"def"
}
]
}
}
使用上面的代码片段,我遇到了编译错误:
Error:(147, 81) could not find implicit value for parameter d:
io.circe.Decoder[List[com.packagename.model.Clip]]
cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]
我做错了什么?如何使用 circe 为 list/array 个简单项目设置解码?
Circe 正在为 List[Clip]
寻找隐式声明的解码器,但找不到。
我怀疑您没有手动或(半)自动定义解码器。您可以按照官方文档 https://circe.github.io/circe/codec.html.
来完成这两项操作不幸的是,我无法提供比这更详细的信息,因为这个问题相当模糊。当提供更多详细信息时,我会更新我的答案。
感谢您的帮助。在离开一段时间并以新的眼光回来后,我能够弄明白。
我认为我使用 downArray 函数出错了。
我的解决方案是执行以下操作:
override def main(args: Array[String]): Unit = {
import ClipCodec.decodeClip
val json = parse(Source.fromFile("playlist.json").mkString).right.get
val clips = json.hcursor.downField("params").downField("playlist")
.downField("items").as[Seq[Clip]]
}
为了完整起见,您可以创建一个自定义解码器,在其处理中包含导航,而不是导航到 JSON 值然后解码剪辑:
import io.circe.Decoder, io.circe.generic.auto._
case class Clip(clipId: String, name: String)
val decodeClipsParam = Decoder[List[Clip]].prepare(
_.downField("params").downField("playlist").downField("items")
)
然后如果你有这个:
val json = """{ "params": {
"playlist": {
"name": "Sample Playlist",
"items": [
{
"clipId":"xyz",
"name":"abc"
},
{
"clipId":"pqr",
"name":"def"
}
]
}
}}"""
你可以这样使用解码器:
scala> io.circe.parser.decode(json)(decodeClipsParam)
res3: Either[io.circe.Error,List[Clip]] = Right(List(Clip(xyz,abc), Clip(pqr,def)))
我可能会更进一步,使用自定义案例 class:
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder
case class Clip(clipId: String, name: String)
case class PlaylistParam(name: String, items: List[Clip])
object PlaylistParam {
implicit val decodePlaylistParam: Decoder[PlaylistParam] =
deriveDecoder[PlaylistParam].prepare(
_.downField("params").downField("playlist")
)
}
现在你可以这样写:
scala> io.circe.parser.decode[PlaylistParam](json).foreach(println)
PlaylistParam(Sample Playlist,List(Clip(xyz,abc), Clip(pqr,def)))
不过,您想如何拆分导航和解码主要是个人喜好问题。