3

I defined a user which has a "video" information:

case class User(name:String, video: Option[Video])
case class Video(title:String, url:String)

And we have such a json:

{
   "name": "somename",
   "video": {
       "title": "my-video",
       "url": "https://youtube.com/watch?v=123123"
   }
}

I can use such code to parse it:

implicit def DecodeUser: DecodeJson[User] = for {
    name <- as[String]("name")
    video <- as[Option[Video]]("video")
} yield User(name, video)

implicit def DecodeVideo: DecodeJson[Option[Video]] = for {
    titleOpt <- as[Option[String]]("title")
    urlOpt <- as[Option[String]]("url")
} yield (titleOpt, urlOpt) match {
   case (Some(title), Some(url)) => Video(title, url)
   case _ => None
}

From the DecodeVideo, you can see I just want to provide the video only if both "title" and "url" provided.

It's working well if the json contains "video" section. But if it doesn't, argonaut will report that "video" section is not provided.

How to make "video" optional?

Freewind
  • 193,756
  • 157
  • 432
  • 708
  • What version of argonaut are you using? I can't find this `as[T]` method that you're using or any documentation on this approach to deserialization on their website. – Nate Oct 22 '14 at 18:10

1 Answers1

-1

I can't seem to figure out how your code integrates with argonaut. All instances of the method as[T] don't seem to match the signature that you're using. Anyways, here's a similar problem and the solution:

object Test {

  case class Video(title: String, url: String)

  def test(titleOptIn: List[Option[String]], urlOptIn: List[Option[String]]): List[Option[Video]] = {
    for {
      titleOpt <- titleOptIn
      urlOpt <- urlOptIn
    } yield (titleOpt, urlOpt) match {
      case (Some(title), Some(url)) => Some(Video(title, url))
      case _ => None.asInstanceOf[Option[Video]]
    }
  }

  def main(args: Array[String]): Unit = {
    test(List(Some("t")), List(Some("u"), None)).foreach(println)
  }
}

// Has Output:
// Some(Video(t,u))
// None

Specifically note that the yield comprehension should return an Option[String] since your yield is likely to be wrapping the result in DecodeJson just like my example wraps it in a List. Note that asInstanceOf on None is optional; IntelliJ complains if it's not there but it actually compiles just fine.

The specific thing that I believe you're missing is wrapping Video in Some.

Nate
  • 2,205
  • 17
  • 21