使用 scala argonaut 对多个嵌套 类 进行复杂编码
Complex Encoding of multiple nested classes using scala argonaut
下面的MainClassEncodeJson
方法有什么问题?
一直关注使用 Scala 进行隐式 JSON 转换的示例 http://lollyrock.com/articles/scala-implicit-conversion/
这个问题类似于:Encoding nested classes using scala argonaut
区别在于额外的 layer/s 嵌套。
编译器出现以下错误:
Cannot resolve reference EncodeJson with such signature
提前致谢。
已包含编码器和解码器以确保完整性
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)
}
将 6.1 版与 Scalaz 7 一起使用。1.x 我使用 CodecJson\[_\]
和 casecodecN
函数得到以下编译结果。
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 := "Whosebug"
scalaVersion := "2.11.7"
val scalazVersion = "7.1.0"
val argonautVersion = "6.1"
libraryDependencies ++= Seq(
"org.scalaz" %% "scalaz-core" % scalazVersion,
"io.argonaut" %% "argonaut" % argonautVersion,
)
通过使用这种定义 encode/decode 的方式 - 当使用简单情况 classes 来体现 JSON 对象文字时 - 我认为我们最终会得到更简单的代码来维护,因为提高了可读性和减少了移动部分(这都是声明性的,而不是遵循理解逻辑)。我还发现它是一个更可组合的问题定义,所以我可以从小事做起,而不用担心包装内壳的内容 classes.
您需要按照 需要 的顺序放置 CodecJson[_]
隐式(即在使用它们的外部 class 编解码器隐式之前定义内部情况) 否则您将收到编译时警告。
Argonaut 网站上的 QuickStart 文档中还有一个有用的示例。
下面的MainClassEncodeJson
方法有什么问题?
一直关注使用 Scala 进行隐式 JSON 转换的示例 http://lollyrock.com/articles/scala-implicit-conversion/
这个问题类似于:Encoding nested classes using scala argonaut
区别在于额外的 layer/s 嵌套。
编译器出现以下错误:
Cannot resolve reference EncodeJson with such signature
提前致谢。
已包含编码器和解码器以确保完整性
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)
}
将 6.1 版与 Scalaz 7 一起使用。1.x 我使用 CodecJson\[_\]
和 casecodecN
函数得到以下编译结果。
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 := "Whosebug"
scalaVersion := "2.11.7"
val scalazVersion = "7.1.0"
val argonautVersion = "6.1"
libraryDependencies ++= Seq(
"org.scalaz" %% "scalaz-core" % scalazVersion,
"io.argonaut" %% "argonaut" % argonautVersion,
)
通过使用这种定义 encode/decode 的方式 - 当使用简单情况 classes 来体现 JSON 对象文字时 - 我认为我们最终会得到更简单的代码来维护,因为提高了可读性和减少了移动部分(这都是声明性的,而不是遵循理解逻辑)。我还发现它是一个更可组合的问题定义,所以我可以从小事做起,而不用担心包装内壳的内容 classes.
您需要按照 需要 的顺序放置 CodecJson[_]
隐式(即在使用它们的外部 class 编解码器隐式之前定义内部情况) 否则您将收到编译时警告。
Argonaut 网站上的 QuickStart 文档中还有一个有用的示例。