如何在scala中使用Circe解码JSON列表/数组 [英] How to Use Circe for Decoding JSON Lists/Arrays in Scala

查看:339
本文介绍了如何在scala中使用Circe解码JSON列表/数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有代码段

cursor.downField("params").downField("playlist").downField("items").as[List[Clip]]

其中Clip是字符串和数字的简单案例类.传入的Json应该包含一个带有项目"数组的json对象播放列表",其中每个项目都是一个剪辑.所以json应该看起来像

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

{
  "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]]

我做错了什么?您如何使用circe设置简单项目列表/数组的解码?

What am I doing wrong? How do you setup decoding for a list/array of simple items using circe?

推荐答案

为了完整起见,您可以创建一个自定义解码器,在处理过程中包括导航:

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:

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")
    )
}

现在您可以这样写:

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.

这篇关于如何在scala中使用Circe解码JSON列表/数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆