gpt4 book ai didi

scala - 使用 argonaut 解码为递归 ADT

转载 作者:行者123 更新时间:2023-12-02 03:17:36 25 4
gpt4 key购买 nike

我正在尝试像这样解析 json

{
"element": "string",
"content": "application/json"
}

element 决定了 json 的类型。但是我的代码无法解析。

http://scastie.org/15213

import scalaz._, Scalaz._
import argonaut._, Argonaut._, Shapeless._

case class ArrayAttributes(default: List[StringElement])

sealed trait Element
case class StringElement(content: String) extends Element
case class ArrayElement(attributes: ArrayAttributes, content: List[Element]) extends Element
case class Reference(element: String) extends Element { def content = element }

object Parser {

def kindDecode[T](
kinds: Map[String, DecodeJson[T]],
fail: HCursor => DecodeResult[T] = { c: HCursor => DecodeResult.fail[T]("expected one of ${kind.keys}", c.history) }): DecodeJson[T] = DecodeJson(c =>
(c --\ "element").as[String].flatMap { kind =>
kinds.get(kind).map(_.decode(c)).getOrElse(fail(c))
}
)

implicit def elementDecode: DecodeJson[Element] = kindDecode(
Map(
"string" -> DecodeJson.of[StringElement].map(identity[Element]),
"array" -> arrayDecode.map(identity[Element])
),
{ c => DecodeJson.of[Reference].decode(c).map(identity[Element]) }
)

def arrayDecode: DecodeJson[ArrayElement] = jdecode2L(ArrayElement.apply)("attributes", "content")

}

最佳答案

我将用 argonaut-shapeless 的当前里程碑 (1.0.0-M1) 来回答,它自 0.3.1 版本以来已经有相关的补充.

它允许为总和类型指定所谓的 JsonSumCodec,这会驱动子类型的编码/区分方式。

通过在其伴生对象中为 Element 定义一个,例如

implicit val jsonSumCodecForElement = derive.JsonSumCodecFor[Element](
derive.JsonSumTypeFieldCodec(
typeField = "element",
toTypeValue = Some(_.stripSuffix("Element").toLowerCase)
)
)

您的示例正常工作:

> Parse.decodeEither[Element](member)
res1: (String \/ (String, CursorHistory)) \/ Element =
\/-(StringElement(application/json))
上面的

JsonSumCodecFor是一个类型类,它为给定的类型提供了一个JsonSumCodec,这里是Element。作为 JsonSumCodec,我们选择 JsonSumTypeFieldCodec,它默认使用字段 “type” 来区分子类型。在这里,我们选择 "element" 而不是 "type",我们还转换子类型名称(toTypeValue 参数),这样这些匹配示例输入的名称。

关于scala - 使用 argonaut 解码为递归 ADT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35650764/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com