1

What is wrong with the MainClassEncodeJson method below?

Have been following the example for Implicit JSON conversion with Scala http://lollyrock.com/articles/scala-implicit-conversion/

This question is similar to: Encoding nested classes using scala argonaut

The difference being an additional layer/s of nesting.

Am getting the following error from the compiler:

Cannot resolve reference EncodeJson with such signature

Thanks for in advance.

Have included the Encoder and Decoder for completeness


object ImplicitConversion {

  case class MainClass (txid: String,hat: Hat,version: Int,bot: Bot, time: Int, locktime: Int)
  case class Hat (value: Float,n: Int,nxt: Nxt)
  case class Nxt (typetx: String,reqsigs: Int,addresses: List[Address])
  case class Bot (base: String,sequence: Int)
  case class Address (address: String)


  // implicit conversion with argonaut
  implicit def MainClassEncodeJson: EncodeJson[MainClass] =
    EncodeJson((m: MainClass) =>
      ("txid" := m.txid) ->:
      ("hat" := Json (
          ("value" := m.hat.value),
          ("n" := m.hat.n),
          ("nxt" := Json (
            ("typetx" := m.hat.nxt.typetx),
            ("reqsigs" := m.hat.nxt.reqsigs),
            ("addresses" := m.hat.nxt.addresses)
          )
            )  ->: jEmptyObject
        )
          ) ->: jEmptyObject
      ("version" := m.version) ->:
      ("bot" := Json (
              ("base" := m.bot.base)
              ("sequence" := m.bot.sequence)
        )
          ) ->: jEmptyObject
        ("time" := m.time) ->: 
        ("locktime" := m.locktime) ->:
    )

  implicit def MainClassDecodeJson: DecodeJson[MainClass] =
    DecodeJson(c => for {
      txid <- (c --\ "txid").as[String]
      hat <- (c --\ "hat").as[Json]
      version <- (c --\ "version").as[Int]
      bot <- (c --\ "bot").as[Json]
      time <- (c --\ "time").as[Int]
      locktime <- (c --\ "locktime").as[Int]

      // extract data from hat
      value <- (hat.acursor --\ "value").as[Float]
      n <- (hat.acursor --\ "n").as[Int]
      nxt <- (hat.acursor --\ "nxt").as[Json]

      // extract data from nxt
      typetx <- (nxt.acursor --\ "typetx").as[String]
      reqsigs <- (nxt.acursor --\ "reqsigs").as[Int]
      addresses <- (nxt.acursor --\ "addresses").as[List[Address]]

      // extract data from bot
      base <- (bot.acursor --\ "base").as[String]
      sequence <- (bot.acursor --\ "sequence").as[Int]

    } yield MainClass(txid, hat(value, n, Nxt(typetx, reqsigs, addresses)), 
                     version, Bot(base, sequence), time, locktime)

}
4

1 回答 1

2

将 6.1 版与 Scalaz 7.1.x 一起使用,我使用CodecJson\[_\]andcasecodecN函数得到了以下编译。

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

object ImplicitConversion {

  case class MainClass( txid: String
                      , hat: Hat
                      , version: Int
                      , bot: Bot
                      , time: Int
                      , locktime: Int)

  case class Hat( value: Float
                , n: Int
                , nxt: Nxt)

  case class Nxt( typetx: String
                , reqsigs: Int
                , addresses: List[Address])

  case class Bot( base: String
                , sequence: Int)

  case class Address(address: String)


  implicit val botCodec: CodecJson[Bot] =
    casecodec2(Bot.apply, Bot.unapply)("base", "sequence")

  implicit val addressCodec: CodecJson[Address] =
    casecodec1(Address.apply, Address.unapply)("address")

  implicit val nxtCodec: CodecJson[Nxt] =
    casecodec3(Nxt.apply, Nxt.unapply)("typetx", "reqsigs", "addresses")

  implicit val hatCodec: CodecJson[Hat] =
    casecodec3(Hat.apply, Hat.unapply)("value", "n", "nxt")

  implicit val mainClassCodec: CodecJson[MainClass] =
    casecodec6(MainClass.apply, MainClass.unapply)("txid", "hat", "version", "bot", "time", "locktime")

}

我的build.sbt样子是这样的:

name := "stackoverflow"

scalaVersion := "2.11.7"

val scalazVersion = "7.1.0"

val argonautVersion = "6.1"

libraryDependencies ++= Seq(
  "org.scalaz"      %% "scalaz-core"    % scalazVersion,
  "io.argonaut"     %% "argonaut"       % argonautVersion,
)

通过使用这种定义编码/解码的方式 - 当使用简单的案例类来体现 JSON 对象文字时 - 我认为由于提高了可读性和减少了移动部件,我们最终得到了更简单的代码来维护(这都是声明性的,而不是遵循理解逻辑)。我还发现它是对问题的更可组合的定义,因此我可以从小处着手,而不必担心包装内部案例类的内容。

您将需要按需要CodecJson[_]的顺序放置隐式(即在使用它们的外部类之前定义内部案例类编解码器隐式),否则您将收到编译时警告。

Argonaut 网站上的QuickStart文档中也有一个有用的示例。

于 2016-03-02T13:50:57.847 回答