Search code examples
jsonscalaplayframework-2.2

Play! Scala: Json reader and additional class field


I'm using Play! Scala 2.2 and I'm reading json as following and it works great:

case class YoutubeTrack(//artistId: String,
                          videoId: String,
                          title: String,
                          thumbnail: Option[String] )
val youtubeTrackReads: Reads[YoutubeTrack] = (
      (__ \ "id" \ "videoId").read[String] and
        (__ \ "snippet" \ "title").read[String] and
        (__ \ "snippet" \ "thumbnails" \ "default" \ "url").readNullable[String]
      )(YoutubeTrack)

Now I would like to add a field to my YoutubeTrack class (artistId that is commented in the class declaration). This field is a variable that I define somewhere else.

How can I add this field to my YoutubeTrack at the same time that I read the json i.e. I would like to do something like:

val youtubeTrackReads: Reads[YoutubeTrack] = (
      (__ \ "id" \ "videoId").read[String] and
        (__ \ "snippet" \ "title").read[String] and
        (__ \ "snippet" \ "thumbnails" \ "default" \ "url").readNullable[String]
      )((artistId, videoId, title, url) => YoutubeTrack(artistId, videoId, title, url))

Solution

  • Given function

    def toArtistId(
        videoId: String,
        title: String,
        thumbnail: Option[String]): String = ...
    
    1. You can even add your artist id without changing a reader

      case class YoutubeTrack(
          videoId: String,
          title: String,
          thumbnail: Option[String]) {
          val artistId = toArtistId(videoId, title, thumbnail)
      }
      
    2. Or change your reader like this

      (
          (__ \ "id" \ "videoId").read[String] and 
          (__ \ "snippet" \ "title").read[String] and
          (__ \ "snippet" \ "thumbnails" \ "default" \ "url").readNullable[String]
      )((videoId, title, thumbnail) => 
           YoutubeTrack(toArtistId(videoId, title, thumbnail), videoId, title, thumbnail)
      )
      
    3. Or even like this

      def artistReader(artistId: String): Reads[YoutubeTrack] = {
          (
              (__ \ "id" \ "videoId").read[String] and
              (__ \ "snippet" \ "title").read[String] and
              (__ \ "snippet" \ "thumbnails" \ "default" \ "url").readNullable[String]
          )((videoId, title, thumbnail) => 
              YoutubeTrack(artistId, videoId, title, thumbnail))
      }
      
      artistReader("A")