json - 用于蛇案例 ADT 的 ConfiguredJsonCodec
问题描述
我必须使用一个 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"
原因是派生机制认为 case-object-only 和 case-object-and-case-classes 之间没有区别,所以对于这样的代码
trait MyADT
object MyADT {
case class Value1(value: String) extends MyADT
case class Value2(value: String) extends MyADT
}
您只需将 sum 部分的编解码器组合在一起
val decoder: Decoder[MyADT] = Decoder[Value1].widen orElse Decoder[Value2].widen
Value1
即使您对Value2
. Derivation 认为这两种情况之间没有区别,因此他们更愿意始终使用判别场来保证安全。(这在 docs 中讨论)。
但是,如果您知道自己正在构建枚举,则可以简单地使用带有 circe 支持的 enumeratum:
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
}
这将实现您的目标,尽管方式不同。
推荐阅读
- javascript - 如何从 jQuery.fn.init() 和 jQuery.fn.init 中取出特定值 [prevObject: jQuery.fn.init()]
- javascript - 在数组数组上使用 math.random 的问题
- highcharts - Highcharts 组织结构图的拖放功能
- python - 从 json 文件中提取 URL
- javascript - 如何比较两个对象数组并删除 JavaScript 中的重复项?
- javascript - 如何在我的网站上的光标上制作十字准线效果
- azure-devops - 无法将工件从一个阶段复制到 Azure 管道中的另一个阶段
- java - Eclipse 使用 Maven 更改项目的版本?
- google-sheets - GoogleFinance 在获取股票报价时经常返回#N/A 和内部错误消息
- r - 根据其他列在data.frame中添加一个新列