How to convert Scala Map into JSON String?

44,911

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)
Share:
44,911

Related videos on Youtube

null
Author by

null

null

Updated on August 21, 2020

Comments

  • null
    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
    null over 9 years
    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.
  • Dima
    Dima over 9 years
    You can download it from may usual places. Like here
  • null
    null over 9 years
    Hi, mohit, care to give full code example? If I just write write(m), I would get not found compile error on it.
  • mohit
    mohit over 9 years
    @suud - updated. It will work after adding json4s dependency in sbt for jackson.
  • Dima
    Dima over 9 years
    libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala" % "2.4.4"
  • null
    null over 9 years
    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 :)
  • mohit
    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
    null over 9 years
    Hi, 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 using DefaultFormats.
  • mohit
    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
    null over 9 years
    Hi, thanks for the information. In my case, there is no POJO (or POSO perhaps) involved.
  • null
    null over 9 years
    Is it ok in term of scala's good practice to use java class in scala code?
  • bill_e
    bill_e over 9 years
    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.
  • thewaywewere
    thewaywewere almost 7 years
    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.
  • LexH
    LexH almost 5 years
    What happens when a string contains a backslash or a literal quote mark?
  • seb
    seb almost 5 years
    Beware, it does not recurse, and will translate nested objects to their string representation!
  • saumilsdk
    saumilsdk over 3 years
    I also got same error. Fix is mapper.registerModule(new DefaultScalaModule())
  • saumilsdk
    saumilsdk over 3 years
    You should create new object. E.g mapper.registerModule(new DefaultScalaModule())
  • DataMacGyver
    DataMacGyver about 3 years
    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.