30

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.

asked Jan 14, 2015 at 16:44
0

8 Answers 8

31

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)
null
9,19417 gold badges72 silver badges99 bronze badges
answered Jan 14, 2015 at 17:27

6 Comments

Hi, mohit, care to give full code example? If I just write write(m), I would get not found compile error on it.
@suud - updated. It will work after adding json4s dependency in sbt for jackson.
Your 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 :)
@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 :)
@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)
|
23
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}

Jason Heo
10.3k2 gold badges38 silver badges72 bronze badges
answered Jun 23, 2017 at 0:23

2 Comments

While 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.
You should create new object. E.g mapper.registerModule(new DefaultScalaModule())
10

You need to tell jackson how to deal with scala objects: mapper.registerModule(DefaultScalaModule)

answered Jan 14, 2015 at 17:06

4 Comments

I got compile error: DefaultScalaModule is not found. I googled up and found out I have to add import com.fasterxml.jackson.module.scala.DefaultScalaModule, but the class is not found.
You can download it from may usual places. Like here
libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala" % "2.4.4"
I also got same error. Fix is mapper.registerModule(new DefaultScalaModule())
7
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()
answered Apr 11, 2018 at 9:16

2 Comments

Beware, it does not recurse, and will translate nested objects to their string representation!
Also, 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.
3

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)
answered Jan 15, 2015 at 14:36

1 Comment

Hi, thanks for the information. In my case, there is no POJO (or POSO perhaps) involved.
1

One thing you can do using the Jackson library is to use a java HashMap object, instead of a Scala one. Then you can basically use the same "without success" code you already wrote.

import org.codehaus.jackson.map.ObjectMapper
val mapper = new ObjectMapper()
val jmap = new java.util.HashMap[String, Int]()
jmap.put("dog", 4)
jmap.put("cat", 1)
// convert to json formatted string
val jstring = mapper.writeValueAsString(jmap)
println(jstring)

returns

jstring: String = {"dog":4,"cat":1} 
answered Jan 19, 2015 at 15:57

2 Comments

Is it ok in term of scala's good practice to use java class in scala code?
When 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.
0

In case somebody is looking for a solution using standard libraries.

def toJson(query: Any): String = query match {
 case m: Map[String, Any] => s"{${m.map(toJson(_)).mkString(",")}}"
 case t: (String, Any) => s""""${t._1}":${toJson(t._2)}"""
 case ss: Seq[Any] => s"""[${ss.map(toJson(_)).mkString(",")}]"""
 case s: String => s""""$s""""
 case null => "null"
 case _ => query.toString
}
answered May 3, 2019 at 12:15

1 Comment

What happens when a string contains a backslash or a literal quote mark?
-1

The following snippet extracted from the official scala site worked well for me. It uses uPickle library.

val map: Map[String, Int] =
 Map("Toolkitty" -> 3, "Scaniel" -> 5)
val jsonString: String = upickle.default.write(map)
println(jsonString)
// prints: {"Toolkitty":3,"Scaniel":5}

https://docs.scala-lang.org/toolkit/json-serialize.html

answered Jul 10, 2023 at 23:56

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
@XMehdi01, I made the suggested fix. May I kindly know does this meet the expectations? I still see one downvote. Or else I can delete the answer. - Thanks

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.