使用Argonaut

时间:2016-02-25 13:32:37

标签: scala argonaut

我试图用refract解析json与argonaut的风格。

Scastie:http://scastie.org/15196

错误:尝试解码失败的游标上的值:[* .--(meta)]

我不明白为什么它不起作用,meta上的所有内容都是可选的,甚至是Meta本身。

示例JSON:

{
  "element": "member",
  "content": {
    "key": {
      "element": "string",
      "content": "Content-Type"
    },
    "value": {
      "element": "string",
      "content": "application/json"
    }
  }
}
到目前为止

代码:

/***
scalaVersion := "2.11.7"
  val argonautVersion = "6.1"
  val scalazVersion = "7.1.6"
      libraryDependencies ++= Seq(
            "io.argonaut" %% "argonaut" % argonautVersion
          , "org.scalaz" %% "scalaz-core" % scalazVersion
          , "com.github.alexarchambault" %% s"argonaut-shapeless_$argonautVersion" % "0.3.1"
          , "org.scalatest" %% "scalatest" % "2.2.4" % "test"
      )


*/


import scala.language.existentials
import scalaz._, Scalaz._
import argonaut._, Argonaut._, Shapeless._

case class Document(content: Seq[Int])

case class Meta(description: Option[String], classes: Seq[String], id: Option[String])

case class Member(meta: Option[Meta], attributes: Option[MemberAttributes], content: KeyValue)
case class MemberAttributes(typeAttributes: Seq[String], default: Seq[StringElement])
case class KeyValue(key: StringElement, value: Element[_])
sealed trait Element[T] {
  def content: T
}
case class StringElement(content: String) extends Element[String]
case class ArrayElement(content: Seq[StringElement], attributes: MemberAttributes) extends Element[Seq[StringElement]]

object Parser {
  def validateElement(name: String): HCursor => Boolean = { c =>
    (c --\ "element").as[String].toDisjunction.fold(_ => false, _ == name)
  }
  def decodeAndValidate[T: DecodeJson](name: String): DecodeJson[T] =
    DecodeJson.of[T].validate(validateElement(name), s"element name should be $name")

  def elementDecode: DecodeJson[Element[_]] = DecodeJson(c =>
    (c --\ "element").as[String].flatMap { kind =>
      kind match {
        case "string" => DecodeJson.of[StringElement].decode(c).map({ x => x: Element[_] })
        case "array"  => DecodeJson.of[ArrayElement].decode(c).map({ x => x: Element[_] })
        case _        => DecodeResult.fail("expected string or array as member value", c.history)
      }
    }
  )
  def stringDecode: DecodeJson[StringElement] = decodeAndValidate[StringElement]("string")
  implicit def keyvalueDecode: DecodeJson[KeyValue] = jdecode2L(KeyValue.apply)("key", "value")(stringDecode, elementDecode)

  def documentDecode: DecodeJson[Document] = decodeAndValidate[Document]("parseResult")
  def memberDecode: DecodeJson[Member] = decodeAndValidate[Member]("member")
}

object Decoders {
  implicit def documentDecode: DecodeJson[Document] = Parser.documentDecode
  implicit def memberDecode: DecodeJson[Member] = Parser.memberDecode
}
object Main extends App {

  import Decoders._

  val shortMember = """
{
  "element": "member",
  "content": {
    "key": {
      "element": "string",
      "content": "Content-Type"
    },
    "value": {
      "element": "string",
      "content": "application/json"
    }
  }
}
"""

  println(Parse.decodeEither[Member](shortMember))

}

1 个答案:

答案 0 :(得分:0)

argonaut-shapelessOption有不同的看法。在为Option手动指定案例类的解码器后,它按预期工作。