首页 > 解决方案 > 在隐式范围内没有可用于 scala.collection.immutable.List 的 Reads 实例

问题描述

我有嵌套的案例类将 json 对象反序列化为对象“C”。json 看起来像这样:

val jsonResp = {
 "parent":{
   "children": [
     {"name": "a",
      "house": "blue"}
     {"name": "b",
      "house": "green"}
   ]
 }
}

我有嵌套类来反序列化这些值。

case class Parent(children: Children)
case class Children(children: List[Child])
case class Child(name: String, house: String)

我正在尝试在此处的第 0 个索引处获取“子”对象:

val parent = jsonResp.as[Parent](Json.format[Parent])
val childrenRespObj = jsonResp.as[Children](Json.format[Children])
val child1 = Child(ChildrenRespObj.children.head.name, Child(ChildrenRespObj.children.head.house)

遇到错误:在隐式范围内没有可用于 scala.collection.immutable.List 的读取实例。

既然“儿童”有 List[Child] 作为参数,那么为什么它会抛出错误?我该如何解决这个问题?谢谢。

标签: jsonscaladeserialization

解决方案


Json.format需要依赖Format才能创建Format依赖类型。

您需要确保依赖项在创建依赖项的范围内Format可用。implicitFormatJson.format[...]

import play.api.libs.json._

object CustomJsonImplicits {
  implicit val childFormat = Json.format[Child]
  implicit val childrenFormat = Json.format[Children]
  implicit val parentFormat = Json.format[Parent]
}

import CustomJsonImplicits._

val parent = jsonResp.as[Parent]

val childAtZerothIndex = parent.children.children(0)

编辑

我刚刚意识到你的案例类对于这个 json 有点错误。您必须记住,自动生成的 Format 实例对 json 结构非常特殊。修改正确性。

import play.api.libs.json._

// it is good practice to define case classes as final
// but this code will work the same even without final
final case class Response(parent: Parent)
final case class Parent(children: List[Child])
final case class Child(name: String, house: String)

object CustomJsonImplicits {
  implicit val childFormat = Json.format[Child]
  implicit val parentFormat = Json.format[Parent]
  implicit val responseFormat = Json.format[Response]
}

val jsonResp = 
  s"""|{
      |  "parent": {
      |    "children": [
      |      { "name": "a", "house": "blue" },
      |      { "name": "b", "house": "green" }
      |    ]
      |  }
      |}""".stripMargin

import CustomJsonImplicits._

val jsValue = Json.parse(jsonResp)

val response = jsValue.as[Response]

println(response)

val childAtZerothIndex = response.parent.children(0)

println(childAtZerothIndex)

此外,您可以尝试将此代码作为 Scastie 片段运行在 - https://scastie.scala-lang.org/sarveshseri/dfBs6PvOT8KDTV4ITdTByA/9


推荐阅读