将 Json 对象解析为 Scala 中的案例类?

Posted

技术标签:

【中文标题】将 Json 对象解析为 Scala 中的案例类?【英文标题】:Parse Json Objects into case classes in Scala? 【发布时间】:2019-01-18 21:01:40 【问题描述】:

我有一个 Json 对象数组。所有这些对象都遵循以下两种结构之一: 第一个是这样的:


            "uuid": "321,
            "uuidType": "series",
            "title": "a movie",
            "segments": [
                "movie"
            ],
            "seriesIds": [
                "123"
            ]
        

第二个是这样的:

 
            "uuid": "1234",
            "uuidType": "programme",
            "title": "programme title",
            "type": "movie",
            "segments": [
                "movies"
            ],
            "programmeIds": [
                "321"
            ]
        

但是,我想像这样将这些对象解析到同一个案例类中:

case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], ids: List[String])

因此,对于第二种类型的对象,类型键和值将被忽略,来自第一个对象的 seriesIds 和来自第二个对象的 programIds 都将进入案例类的 ids 部分。但是我不知道该怎么做!我正在使用 Circe 对 json 进行解码/编码。

【问题讨论】:

尝试使用 circe 游标将 ids 字段填充到已解析的 Json AST 中,然后再将其转换为您的类型。 【参考方案1】:

您可以在 SearchResult 对象伴侣中放置自定义解码器

斯卡拉 2.12 大约 0.9.3

import io.circe._
import io.circe.parser._

object Main extends App 

  val jsonA =
    """
         "uuid": "321",
         "uuidType": "series",
         "title": "a movie",
         "segments": [
            "movie"
         ],
         "seriesIds": [
            "123"
         ]
       """

  val jsonB =
    """
        "uuid": "1234",
        "uuidType": "programme",
        "title": "programme title",
        "type": "movie",
        "segments": [
          "movies"
        ],
        "programmeIds": [
          "321"
        ]
       """

  case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], ids: List[String])

   object SearchResult 

    implicit val decoder: Decoder[SearchResult] = Decoder.instance  h =>

    for 
      uuid <- h.get[String]("uuid")
      uuidType <- h.get[String]("uuidType")
      title <- h.get[String]("title")
      segments <- h.get[List[String]]("segments")
      ids <- 
        h.getOrElse[List[String]]("seriesIds")(h.get[List[String]]("programmeIds").getOrElse(Nil))
      
     yield SearchResult(uuid, uuidType, title, segments, ids)

   

  

  val obj1 = decode[SearchResult](jsonA)
  println(obj1)

  val obj2 = decode[SearchResult](jsonB)
  println(obj2)

  

【讨论】:

谢谢!这正是我想要的!【参考方案2】:

您可以在 circe 中编写自定义代码以获得您想要的效果,但在我看来,使用 circe 自动反序列化并将您的案例类定义为更简单

case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], programmeIds: Option[List[String]], seriesIds: Option[List[String]])

并使用简单的 scala 代码将其转换为 id

【讨论】:

以上是关于将 Json 对象解析为 Scala 中的案例类?的主要内容,如果未能解决你的问题,请参考以下文章

JSON将Scala案例类序列化为仅字符串和整数

scala 将 Array[String] 转换为案例类

使用 circe 在 Scala 中 JSON 将嵌套字段解码为 Map[String, String]

在Scala中解析内容为Json格式的文件

将数据转换为 spark scala 中的类对象列表

Scala使用circe将None编码为NaN json值