首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用argonaut译码成递归ADTs

用argonaut译码成递归ADTs
EN

Stack Overflow用户
提问于 2016-02-26 11:40:16
回答 1查看 246关注 0票数 3

我想解析json就像

代码语言:javascript
复制
{
  "element": "string",
  "content": "application/json"
}

其中,element决定json的类型。但我的代码无法解析。

http://scastie.org/15213

代码语言:javascript
复制
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")

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-26 13:28:44

我将用argonaut (1.0.0-M1)的当前里程碑来回答这个问题,它在0.3.1版本之后就有了相关的添加。

它允许为sum类型指定所谓的JsonSumCodecs,从而驱动子类型的编码/识别方式。

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

代码语言:javascript
复制
implicit val jsonSumCodecForElement = derive.JsonSumCodecFor[Element](
  derive.JsonSumTypeFieldCodec(
    typeField = "element",
    toTypeValue = Some(_.stripSuffix("Element").toLowerCase)
  )
)

你的例子很管用:

代码语言:javascript
复制
> Parse.decodeEither[Element](member)
res1: (String \/ (String, CursorHistory)) \/ Element =
  \/-(StringElement(application/json))

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35650764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档