简体   繁体   English

使用scala argonaut的多个嵌套类的复杂编码

[英]Complex Encoding of multiple nested classes using scala argonaut

What is wrong with the MainClassEncodeJson method below? 下面的MainClassEncodeJson方法有什么问题?

Have been following the example for Implicit JSON conversion with Scala http://lollyrock.com/articles/scala-implicit-conversion/ 一直在使用Scala进行隐式JSON转换的示例http://lollyrock.com/articles/scala-implicit-conversion/

This question is similar to: Encoding nested classes using scala argonaut 这个问题类似于: 使用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. 在Scalaz 7.1.x中使用6.1版时,我得到了以下内容,可以使用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")

}

My build.sbt looks like this: 我的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,
)

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). 通过使用这种定义编码/解码的方式-当使用简单的案例类来体现JSON对象文字时-我认为由于可读性的提高和运动部件的减少,我们最终得到了更简单的代码来进行维护(与遵循理解逻辑)。 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 (ie define the inner case class codec implicits before outer ones that use them) or you will get compile-time warnings. 你需要把CodecJson[_] implicits 需要的顺序(即使用它们外层标记之前定义的内壳类编解码器implicits),或者你会得到编译时警告。

There is also a helpful example in the QuickStart documentation on the Argonaut website. Argonaut网站上的QuickStart文档中还有一个有用的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM