如何使用带有Scala的Circe库解析变体Json?

时间:2018-11-02 09:42:38

标签: json scala circe

我正在尝试使用案例类为Json模型创建解码器,但我找不到解码json变体列表的方法。

object CirceTester {

  def main(args: Array[String]): Unit = {

    val json = """{
  "foo": "bar",
  "baz": "123.34",
  "list of stuff": [ "4", "5", "6","24545","435.030" ],
  "jsonlist": [ {"name":"Jesus","age":20},{"name":"Pedro","age":45}]
}
"""


     case class Person(name:String,age:Int)

    implicit val decodePerson : Decoder[Person] = {

      Decoder.forProduct2("name","age")(Person.apply)

    }

    val parsedJson = parse(json)


    val list = parsedJson match {
      case Left(parsingFailure) => throw new Exception("Failed to parse Json")
      case Right(parsedJson) => parsedJson.hcursor.downField("jsonlist").as[List[Person]]


    }

  }       
}    

如果以这种方式编写Json可以正常工作,但是如果Json有一个变种Jsons列表(例如jsonlist),则代码将失败。

例如

val json = """{
  "foo": "bar",
  "baz": "123.34",
  "list of stuff": [ "4", "5", "6","24545","435.030" ],
  "jsonlist": [ {"name":"Jesus","age":20},{"name":"Pedro"}]
}
""" 

在这种情况下,jsonlist的第二个元素是另一个Json,它缺少字段“ age”,并且正如我所说的,它将抛出一个Exception。我可以解析嵌套的Json吗,即使它不完全符合case类的结构

1 个答案:

答案 0 :(得分:0)

现在很明显,问题在于从json读取可选值。

更改模型以适合您尝试解析的json结构是这里的最佳选择之一。因此,在这种情况下,age字段必须是可选的: case class Person(name: String, age: Option[Int])

如果您无法更改Person的定义,则可以定义中间case class PersonRecord(name: String, age: Option[Int])并在其中编写自定义def toPerson: Person方法-这样一来,在JSON阅读器中创建自定义逻辑就更加清楚了。