aknuds1
aknuds1

Reputation: 67997

How do I convert a Scala Map consisting of String and Seq[String] values to JSON?

In Play Framework using Scala, how do I convert a Map of String and Seq[String] values to JSON format? The following code produces an error for me:

val objMap = Map("id" -> "id", "tags" -> Seq("tag1", "tag2"))
Json.toJson(objMap)

The resulting error:

No Json serializer found for type scala.collection.immutable.Map[String,Object]. Try to implement an implicit Writes or Format for this type.

Upvotes: 2

Views: 4495

Answers (3)

user2657794
user2657794

Reputation: 278

You can simply do this:

val objMap = Map("id" -> Json.toJson("id"), "tags" -> Json.toJson(Seq("tag1", "tag2")))
Json.toJson(objMap)

Will result in this:

 {"id":"id","tags":["tag1","tag2"]}

Upvotes: 5

Adi
Adi

Reputation: 727

Can you not change the map to

val objMap = Map("id" -> Seq("id"), "tags" -> Seq("tag1", "tag2"))

OR

You could define a case class and an implicit writes, it is easier to define for a case class

case class Post(id: String, tags: Seq[String])

implicit val postWrites = Json.writes[Post]

val objMap = Seq(Post("id1", Seq("tag1", "tag2")))

Json.toJson(objMap)

Upvotes: 3

Vikas Pandya
Vikas Pandya

Reputation: 1988

As the error says you'll need to implement a Writes for Map[String,Object]

here is what it will look like. I have compiled this code and it looks fine. (I assume you're using Play framework). FYI: cases in there are only for starting point. you can add/modify more cases in there based on your requirements.

import play.api.libs.json._
import play.api.libs.json.Writes
import play.api.libs.json.Json.JsValueWrapper

val objMap = scala.collection.immutable.Map("id" -> "id", "tags" -> Seq("tag1", "tag2"))
Json.toJson(objMap)

implicit val writeAnyMapFormat = new Writes[Map[String, Object]] {
def writes(map: Map[String, Object]): JsValue = {
  Json.obj(map.map {
    case (s, a) => {
      val ret: (String, JsValueWrapper) = a match {
        case _: String => s -> JsString(a.asInstanceOf[String])
        case _: java.util.Date => s -> JsString(a.asInstanceOf[String])
        case _: Integer => s -> JsString(a.toString)
        case _: java.lang.Double => s -> JsString(a.toString)
        case None => s -> JsNull
        case JsArray(elements) => s -> JsArray(elements)
        case _ => s -> JsArray(a.asInstanceOf[List[Int]].map(JsNumber(_)))
      }
      ret
    }
  }.toSeq: _*)

}
}

Upvotes: 6

Related Questions