我试图编码/解码以下案例类
case class Person(name: String, age: Int, childs: List[Person])
使用以下代码:
object Person {
implicit def PersonCodecJson =
casecodec3(Person.apply, Person.unapply)("name", "age", "childs")
}
与argonaut,但我得到以下编译器错误:
could not find implicit value for evidence parameter of type argonaut.EncodeJson[List[Person]]
显然,编译器不知道如何处理List [Person]的编码,因为它在如何编码Person的定义中使用。
有没有一种聪明的方法告诉argonaut如何以正确的方式对其进行编码?
更新:感谢Travis:它现在正在编译,但它无法正常工作。
implicit def PersonCodecJson : CodecJson[Person] =
casecodec3(Person.apply, Person.unapply)("name", "age", "childs")
导致无限递归和尝试解码的堆栈溢出
val input = """
[{"name": "parent1", "age": 31, "childs": [{"name": "child1", "age": 2, "childs": []}]},
{"name": "parent2", "age": 29, "childs": []}
]
"""
val persons = input.decodeOption[List[Person]].getOrElse(Nil)
结果
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
at Person$.PersonCodecJson(main.scala:8)
[debug] Thread run-main-1 exited.
[debug] Interrupting remaining threads (should be all daemons).
[debug] Sandboxed run complete..
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
at sbt.BuildCommon$$anonfun$toError$1.apply(Defaults.scala:1653)
at sbt.BuildCommon$$anonfun$toError$1.apply(Defaults.scala:1653)
at scala.Option.foreach(Option.scala:236)
at sbt.BuildCommon$class.toError(Defaults.scala:1653)
at sbt.Defaults$.toError(Defaults.scala:35)
at sbt.Defaults$$anonfun$runTask$1$$anonfun$apply$36$$anonfun$apply$37.apply(Defaults.scala:656)
at sbt.Defaults$$anonfun$runTask$1$$anonfun$apply$36$$anonfun$apply$37.apply(Defaults.scala:654)
at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
at sbt.std.Transform$$anon$4.work(System.scala:64)
这种解码这种嵌套json的方法是否有效?我必须完全解决它吗?或者只是缺少另一小段代码?
答案 0 :(得分:6)
你非常接近 - 你只需要明确指定类型:
object Person {
implicit def PersonCodecJson: CodecJson[Person] =
casecodec3(Person.apply, Person.unapply)("name", "age", "childs")
}
正如Scala不允许您编写没有显式结果类型的递归方法一样,如果没有一个结果类型,它将不会在定义中找到隐式的定义。
不确定它有多聪明,但它确实有效。
答案 1 :(得分:4)
显然问题是casecodec
。如果您手动创建解码器,它可以工作:
implicit def PersonDecodeJson: DecodeJson[Person] =
DecodeJson(c => for {
name <- (c --\ "name").as[String]
age <- (c --\ "age").as[Int]
childs <- (c --\ "childs").as[List[Person]]
} yield Person(name, age, childs))
val persons = input.decodeOption[List[Person]].getOrElse(Nil)
//> persons : List[Person] = List(Person(parent1,31,List(Person(child1,2,List()))), Person(parent2,29,List()))