Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format nullable Seq or List of objects with Play Json and Salat

I want to convert a json to Salat model. I am using Play 2.X Scala Json. I couldn't find any documentations to format nullable Seq. According to https://github.com/novus/salat/wiki/SupportedTypes, I can't use Option[Seq] Or Option[List].

The following json is good, but sometimes 'locations' can be missing.

{
    "id": 581407,
    "locations": [
        {
            "id": 1692,
            "tag_type": "LocationTag",
            "name": "san francisco",
            "display_name": "San Francisco"
        }]
}

These are the classes:

case class User(
 var id: Int,
 var locations: Seq[Tag] = Seq.empty
)

case class Tag(
  id: Int,
  tag_type:String,
  name:String,
  display_name:String
)

How can I format nullable 'locations'?

implicit val format: Format[User] = (
    (__ \ 'id).format[Int] and
    (__ \ 'locations).formatNullable(Seq[Tag])
)
like image 639
angelokh Avatar asked Jan 09 '23 16:01

angelokh


1 Answers

Format is an invariant functor, so you can use inmap to change a Option[Seq[Tag]] format into a format for Seq[Tag]:

import play.api.libs.functional.syntax._
import play.api.libs.json._

implicit val formatTag: Format[Tag] = Json.format[Tag]

implicit val formatUser: Format[User] = (
  (__ \ 'id).format[Int] and
  (__ \ 'locations).formatNullable[Seq[Tag]].inmap[Seq[Tag]](
    o => o.getOrElse(Seq.empty[Tag]),
    s => if (s.isEmpty) None else Some(s)
  )
)(User.apply, unlift(User.unapply))

This will not produce a locations value when serializing a user with no locations, but if you want an empty array in that case you can just change the None in the second argument to inmap to Some(Seq.empty).

like image 145
Travis Brown Avatar answered Jan 15 '23 22:01

Travis Brown