如何解决已配置蛇形ADT的JsonCodec
我必须使用json api,其中有蛇形情况下的离散字符串值列表。
下面的示例有效,但是我想删除手册fooDecoder
,而使用(当前已注释掉)ConfiguredJsonCodec注释。
或更基本的问题:在ADT中将这些离散值建模为案例对象是否有意义,或者还有其他方法吗?
import io.circe._
import io.circe.syntax._
import io.circe.generic.extras.{Configuration,ConfiguredJsonCodec,JsonKey}
import io.circe.parser.parse
implicit val jsonConfig: Configuration = Configuration.default
.withSnakeCaseConstructorNames
.withSnakeCaseMemberNames
//@ConfiguredJsonCodec(decodeOnly = true)
sealed trait Foo
object Foo {
case object FooBar extends Foo
case object FooBaz extends Foo
case object FooWuz extends Foo
}
import Foo._
implicit val fooDecoder: Decoder[Foo] = new Decoder[Foo] {
override def apply(c: HCursor) = c.as[String].map{
case "foo_bar" => FooBar
case "foo_baz" => FooBaz
case "foo_wuz" => FooWuz
}
}
@ConfiguredJsonCodec(decodeOnly = true)
case class Qux(fooFoo: List[Foo])
val input ="""{"foo_foo" : ["foo_bar","foo_baz","foo_wuz"]}"""
val json: Json = parse(input).left.map(println(_)).right.get
json.as[Qux]
完整示例:https://scastie.scala-lang.org/eVFyNMGFRgaw9oEkRveT8g
这使用大约0.13.0
解决方法
所有用于副产物的Circe推导方法都假定存在判别字段,充其量您可以选择其名称。因此支持的格式如下:
{
"type": "foo_bar",}
而不只是
"foo_bar"
原因是,仅案例对象类与案例对象和案例类之间的派生机制没有区别,因此对于此类代码
trait MyADT
object MyADT {
case class Value1(value: String) extends MyADT
case class Value2(value: String) extends MyADT
}
您只需组合求和部分的编解码器
val decoder: Decoder[MyADT] = Decoder[Value1].widen orElse Decoder[Value2].widen
即使您对Value1
进行了编码,您也始终会解码到第一个Value2
。派生认为这两种情况之间没有区别,因此,他们倾向于始终使用区分字段来保持安全。 (这是discussed in docs)。
但是,如果您知道自己正在建立枚举,则可以简单地使用带有枚举支持的枚举:
import enumeratum._
sealed trait Foo extends EnumEntry with Snakecase
object Foo extends Enum[Foo] with CirceEnum[Foo] {
case object FooBar extends Foo
case object FooBaz extends Foo
case object FooWuz extends Foo
val values = findValues
}
这可以实现您所期望的目标,尽管采用不同的方式。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。