How to convert Scala Map into JSON String?
Solution 1
As a non play solution, you can consider using json4s which provides a wrapper around jackson and its easy to use. If you are using json4s then you can convert map to json just by using:
write(m)
//> res0: String = {"name":"john doe","age":18,"hasChild":true,"childs":[{"name":"dorothy","age":5,"hasChild":false},{"name":"bill","age":8,"hasChild":false}]}
--Updating to include the full example--
import org.json4s._
import org.json4s.native.Serialization._
import org.json4s.native.Serialization
implicit val formats = Serialization.formats(NoTypeHints)
val m = Map(
"name" -> "john doe",
"age" -> 18,
"hasChild" -> true,
"childs" -> List(
Map("name" -> "dorothy", "age" -> 5, "hasChild" -> false),
Map("name" -> "bill", "age" -> 8, "hasChild" -> false)))
write(m)
Output:
res0: String = {"name":"john doe","age":18,"hasChild":true,"childs":[{"name"
:"dorothy","age":5,"hasChild":false},{"name":"bill","age":8,"hasChild":false }]}
Alternative way:
import org.json4s.native.Json
import org.json4s.DefaultFormats
Json(DefaultFormats).write(m)
Solution 2
val mapper = new ObjectMapper()
mapper.writeValueAsString(Map("a" -> 1))
result> {"empty":false,"traversableAgain":true}
==============================
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
mapper.writeValueAsString(Map("a" -> 1))
result> {"a":1}
Solution 3
You need to tell jackson how to deal with scala objects: mapper.registerModule(DefaultScalaModule)
Solution 4
val mymap = array.map {
case 1 => ("A", 1)
case 2 => ("B", 2)
case 3 => ("C", 3)
}
.toMap
Using scala.util.parsing.json.JSONObject
, you only need 1 line:
import scala.util.parsing.json.JSONObject
JSONObject(mymap).toString()
Solution 5
If you're working with a well-defined data model, why not define case classes and use Play JSON macros to handle conversion? i.e.
case class Person(name: String, age: Int, hasChild: Boolean, childs: List[Person])
implicit val fmt = Json.format[Person]
val person = Person(...)
val jsonStr = Json.toJson(person)
Related videos on Youtube
Comments
-
null over 3 years
For example, I have this Map value in Scala:
val m = Map( "name" -> "john doe", "age" -> 18, "hasChild" -> true, "childs" -> List( Map("name" -> "dorothy", "age" -> 5, "hasChild" -> false), Map("name" -> "bill", "age" -> 8, "hasChild" -> false) ) )
I want to convert it to its JSON string representation:
{ "name": "john doe", "age": 18, "hasChild": true, "childs": [ { "name": "dorothy", "age": 5, "hasChild": false }, { "name": "bill", "age": 8, "hasChild": false } ] }
I'm currenly working on Play framework v2.3, but the solution doesn't need to use Play JSON library, although it will be nice if someone can provide both Play and non-Play solution.
This is what I have done so far without success:
// using jackson library val mapper = new ObjectMapper() val res = mapper.writeValueAsString(m) println(res)
Result:
{"empty":false,"traversableAgain":true}
I don't understand why I got that result.
-
null over 9 yearsI got compile error:
DefaultScalaModule
is not found. I googled up and found out I have to addimport com.fasterxml.jackson.module.scala.DefaultScalaModule
, but the class is not found. -
Dima over 9 yearsYou can download it from may usual places. Like here
-
null over 9 yearsHi, mohit, care to give full code example? If I just write
write(m)
, I would getnot found
compile error on it. -
mohit over 9 years@suud - updated. It will work after adding json4s dependency in sbt for jackson.
-
Dima over 9 years
libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala" % "2.4.4"
-
null over 9 yearsYour code didn't work when I tried because I use Lift Json version from Json4s, the imports is different. I already know how to solve it, but I'll give you a chance to wrap the answer :)
-
mohit over 9 years@suud - I have changed the imports. I am guessing there will not be any more changes. Anyways, if there are any changes, why don't you go ahead and edit the answer, so that it will be helpful to others who are looking for something similar in future :)
-
null over 9 yearsHi, your solution is a bit different with mine, although both works fine. I just added my solution to your answer. Do you know what is the difference between your solution and mine? I can see you're using implicit
NoTypeHints
and I'm usingDefaultFormats
. -
mohit over 9 years@suud I am not entirely sure. Both tell json4s how to serialize/deserialize. I use no type hints when I want json4s to take care of everything and defaultFormats when I want to override some fields(like date time format)
-
null over 9 yearsHi, thanks for the information. In my case, there is no POJO (or POSO perhaps) involved.
-
null over 9 yearsIs it ok in term of scala's good practice to use java class in scala code?
-
bill_e over 9 yearsWhen using java objects in scala, I recommend not importing at the top of your code, instead instantiating java objects like in the example: "val jmap = new java.util.HashMap(...)" etc. That way your namespace won't get mixed up between java and scala types.
-
thewaywewere almost 7 yearsWhile this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
-
LexH almost 5 yearsWhat happens when a string contains a backslash or a literal quote mark?
-
seb almost 5 yearsBeware, it does not recurse, and will translate nested objects to their string representation!
-
saumilsdk over 3 yearsI also got same error. Fix is mapper.registerModule(new DefaultScalaModule())
-
saumilsdk over 3 yearsYou should create new object. E.g mapper.registerModule(new DefaultScalaModule())
-
DataMacGyver about 3 yearsAlso, it's deprecated (using Scala 2.11.12). I'm not doing something that requires me to worry about that right now but I thought I'd mention it.