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)
}
Using version 6.1 with Scalaz 7.1.x I got the following to compile using the CodecJson\[_\]
and casecodecN
functions.
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")
}
My build.sbt
looks like this:
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,
)
By using this way of defining the encode/decode - when using simple case classes to embody JSON object literals - I think we end up with simpler code to maintain due to improved readability and reduction of moving parts (it's all declarative as opposed to following the for-comprehension logic). I also find it is a more composable definition of the problem so I can start out small without worrying about what wraps inner case classes.
You will need to put the CodecJson[_]
implicits in order of need (i.e. define the inner case class codec implicits before outer ones that use them) or you will get compile-time warnings.
There is also a helpful example in the QuickStart documentation on the Argonaut website.