如何在 Scala 中使用 Circe 解码 JSON 列表/数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/42288948/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Use Circe for Decoding JSON Lists/Arrays in Scala
提问by mattmar10
I have the code snippet
我有代码片段
cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]
Where Clip is a simple case class of strings and numbers. The incoming Json should contain a json object "playlist" with an array of "items" where each item is a clip. So the json should look like
其中 Clip 是字符串和数字的简单 case 类。传入的 Json 应该包含一个 json 对象“播放列表”,其中包含一个“项目”数组,其中每个项目都是一个剪辑。所以json应该看起来像
{
  "playlist": {
      "name": "Sample Playlist",
      "items": [
        {
          "clipId":"xyz", 
          "name":"abc"
        },
        {
          "clipId":"pqr", 
          "name":"def"
        } 
      ]
   }
}
With the code snippet above, I'm getting the compile error:
使用上面的代码片段,我收到编译错误:
 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]]
What am I doing wrong? How do you setup decoding for a list/array of simple items using circe?
我究竟做错了什么?您如何使用 circe 为简单项目的列表/数组设置解码?
回答by Travis Brown
For the sake of completeness, instead of navigating into the JSON value and then decoding the clips, you could create a custom decoder that includes the navigation in its processing:
为了完整起见,您可以创建一个自定义解码器,在其处理中包含导航,而不是导航到 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")
)
And then if you've got this:
然后如果你有这个:
val json = """{ "params": {
  "playlist": {
      "name": "Sample Playlist",
      "items": [
        {
          "clipId":"xyz", 
          "name":"abc"
        },
        {
          "clipId":"pqr", 
          "name":"def"
        } 
      ]
   }
}}"""
You can use the decoder like this:
您可以像这样使用解码器:
scala> io.circe.parser.decode(json)(decodeClipsParam)
res3: Either[io.circe.Error,List[Clip]] = Right(List(Clip(xyz,abc), Clip(pqr,def)))
I'd probably go a step further and use a custom case 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")
    )
}
Now you can just write this:
现在你可以这样写:
scala> io.circe.parser.decode[PlaylistParam](json).foreach(println)
PlaylistParam(Sample Playlist,List(Clip(xyz,abc), Clip(pqr,def)))
How you want to split up the navigation and decoding is mostly a matter of taste, though.
但是,您希望如何拆分导航和解码主要是一个品味问题。
回答by mattmar10
Thanks for the help. I was able to figure it out after stepping away for awhile and coming back with fresh eyes.
谢谢您的帮助。在离开一段时间并以全新的眼光回来后,我能够弄清楚。
I think I was going wrong by using the downArray function.
我想我使用 downArray 函数出错了。
My solution was to do the following:
我的解决方案是执行以下操作:
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]]
  }
回答by acidghost
Circe is looking for an implicitly declared decoder for List[Clip]and cannot find it.
Circe 正在寻找隐式声明的解码器,List[Clip]但找不到它。
I suspect that you have not defined a decoder either manually or (semi)automatically. You can do both by following the official docs https://circe.github.io/circe/codec.html.
我怀疑您没有手动或(半)自动定义解码器。您可以按照官方文档https://circe.github.io/circe/codec.html进行这两种操作。
Unfortunately I cannot provide more detail than this because the question is rather vague. I will update my answer when more details are given.
不幸的是,我无法提供比这更多的细节,因为这个问题相当模糊。当提供更多详细信息时,我会更新我的答案。

