decoding using the case class base type

112 views
Skip to first unread message

simbo1905

unread,
Sep 7, 2013, 6:46:17 PM9/7/13
to argona...@googlegroups.com
Folks, 

I am looking for a good way to decode a set of case classes from json without having to know the actual type of the message e.g. different commands coming down a websocket. Mark was kind enough to answer my question on issue #64 with an example. Trying to extend it though I am running into issues. I am a scala n00b trying to escape from java land so my apologies if its obvious to everyone else. 

The problem is that if I uncomment the two lines to configure the codexes for RoomSize the compiler barfs: 

package argonaut.example

import argonaut._, Argonaut._
import org.specs2.{ScalaCheck, Specification}

abstract class Message
case class RoomSize(size: Int, mType: String = "RoomSize") extends Message
case class CardDrawn(player: Long, card: Int, mType: String = "CardDrawn") extends Message
case class CardSet(cards: List[CardDrawn], mType: String = "CardSet") extends Message

class CardSetExampleMain extends Specification with ScalaCheck {

  implicit lazy val CodecRoomSize: CodecJson[RoomSize] = casecodec2(RoomSize.apply, RoomSize.unapply)("size","mType")
  implicit lazy val CodecCardSet: CodecJson[CardSet] = casecodec2(CardSet.apply, CardSet.unapply)("cards","mType")
  implicit lazy val CodecCardDrawn: CodecJson[CardDrawn] = casecodec3(CardDrawn.apply, CardDrawn.unapply)("player", "card", "mType")

  implicit lazy val CodecMessage: CodecJson[Message] = CodecJson(m => m match {
    //case c @ RoomSize(_,_) => Json { "RoomSize" -> c.asJson }
    case c @ CardSet(_,_) => Json { "CardSet" -> c.asJson }
    case c @ CardDrawn(_,_,_) => Json { "CardDrawn" -> c.asJson}
  } , c =>
    //(c --\ "RoomSize").as[RoomSize].map(identity) |||
      (c --\ "CardSet").as[CardSet].map(identity) |||
      (c --\ "CardDrawn").as[CardDrawn].map(identity)
  )

  val setMessage: Message = CardSet(List(CardDrawn(1L,2),CardDrawn(3L,4)))
  val drawnMessage: Message = CardDrawn(1L,2)

  def is = "JsonExample" ^
    "setMessage " ! {
      setMessage.asJson.as[Message].toOption must beSome(setMessage)
    } ^
    "drawnMessage " ! {
      drawnMessage.asJson.as[Message].toOption must beSome(drawnMessage)
    }


  def main(args: Array[String]): Unit = {
    val value = CardSet(List(CardDrawn(1L,2),CardDrawn(3L,4)))
    println(s"Got some good json ${value.asJson}")

    val jstring =
      """{
        | "cards":[
        |   {"player":"1","card":2,"mType":"CardDrawn"},
        |   {"player":"3","card":4,"mType":"CardDrawn"}
        | ],
        | "mType":"CardSet"
        | }""".stripMargin

    val parsed: Option[CardSet] =
      jstring.decodeOption[CardSet]

    println(s"Got a good object ${parsed.get}")
  }
}


The barf is: 

type mismatch;
 found   : argonaut.DecodeResult[com.github.simbo1905.scrumpoker.CardDrawn]
 required: argonaut.DecodeResult[Product with Serializable with com.github.simbo1905.scrumpoker.Message]
Note: com.github.simbo1905.scrumpoker.CardDrawn <: Product with Serializable with com.github.simbo1905.scrumpoker.Message, but class DecodeResult is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
      (c --\ "CardDrawn").as[CardDrawn].map(identity) |||
                                           ^
Thanks in advance, 

Simon 
Reply all
Reply to author
Forward
0 new messages