Serialize Map[String, Any] with spray json
Asked Answered
S

2

20

How do I serialize Map[String, Any] with spray-json? I try

val data = Map("name" -> "John", "age" -> 42)
import spray.json._
import DefaultJsonProtocol._
data.toJson

It says Cannot find JsonWriter or JsonFormat type class for scala.collection.immutable.Map[String,Any].

Sclerous answered 18/9, 2014 at 15:11 Comment(0)
S
29

Here's an implicit converter I used to do this task:

  implicit object AnyJsonFormat extends JsonFormat[Any] {
    def write(x: Any) = x match {
      case n: Int => JsNumber(n)
      case s: String => JsString(s)
      case b: Boolean if b == true => JsTrue
      case b: Boolean if b == false => JsFalse
    }
    def read(value: JsValue) = value match {
      case JsNumber(n) => n.intValue()
      case JsString(s) => s
      case JsTrue => true
      case JsFalse => false
    }
  }

It was adapted from this post in the Spray user group, but I couldn't get and didn't need to write nested Sequences and Maps to Json so I took them out.

Savitt answered 18/9, 2014 at 15:35 Comment(7)
Awesome, it works for me. I just need to make sure I declare this object BEFORE the other JsonFormat implicits that depend on itPaternity
And hot to use it? I copypasted this code above my immutableMap.toJson. But still getting "Can not find Json writer..." error.Menell
Sorry, Made it work. Looks like I still used mutable map, and it must be immutable in order to this examlpe works.Menell
Thanks. You could simply use 'case true => JsTrue' and 'case false => JsFalse', I think. Simpler - no functional change.Compte
I'm curious why it is not a part of spray-jsonMaecenas
I used the code provided in the post referenced with spray.json 1.3.3 and it works fine with nested elements as well. I guess that this is not included in spray-json because it needs to identify the types of the elements in runtime instead of compilation time...Counterfeit
I cannot understand how this works. The input to write is of type Any. While it should be of type Map[String,Any]. I tried to add this code in my implementation that only requires a Map[String,String] and it obviously does not work.Jilolo
R
8

Another option, which should work in your case, is

import spray.json._
import DefaultJsonProtocol._

data.parseJson.convertTo[Map[String, JsValue]]
Radman answered 14/4, 2015 at 20:6 Comment(5)
I like that you mentioned this, because in many cases using JsValue for the values might be enough for people. It's also more in line with spray.json mentality, imho, than handling Any's.Compte
data is of type Map[String,Any] - what should I import to make it have parseJson method?Bigford
I believe what he meant was data.toJsonJapheth
@Bigford probably a way to dated comment - but for others reading this: you should ensure to import spray.json._ and import DefaultJsonProtocol._Septillion
spent the whole day on this. Solution works like a charm. ...Finally time to go to bed. Thank you very much.Landwehr

© 2022 - 2024 — McMap. All rights reserved.