Как конвертировать Scala Map в строку JSON?
Например, у меня есть это значение карты в 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)
)
)
Я хочу преобразовать его в строковое представление JSON:
{
"name": "john doe",
"age": 18,
"hasChild": true,
"childs": [
{
"name": "dorothy",
"age": 5,
"hasChild": false
},
{
"name": "bill",
"age": 8,
"hasChild": false
}
]
}
В настоящее время я работаю над Play framework v2.3, но для решения не нужно использовать библиотеку Play JSON, хотя было бы неплохо, если бы кто-то мог предоставить решение Play и non-Play.
Это то, что я сделал до сих пор без успеха:
// using jackson library
val mapper = new ObjectMapper()
val res = mapper.writeValueAsString(m)
println(res)
Результат:
{"empty":false,"traversableAgain":true}
Я не понимаю, почему я получил такой результат.
8 ответов
В качестве неигрового решения вы можете рассмотреть возможность использования json4s, который обеспечивает обертку вокруг Джексона и прост в использовании. Если вы используете json4s, вы можете конвертировать карту в json, просто используя:
write(m)
//> res0: String = {"name":"john doe","age":18,"hasChild":true,"childs":[{"name":"dorothy","age":5,"hasChild":false},{"name":"bill","age":8,"hasChild":false}]}
- Обновление, чтобы включить полный пример -
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)
Выход:
res0: String = {"name":"john doe","age":18,"hasChild":true,"childs":[{"name"
:"dorothy","age":5,"hasChild":false},{"name":"bill","age":8,"hasChild":false }]}
Альтернативный способ:
import org.json4s.native.Json
import org.json4s.DefaultFormats
Json(DefaultFormats).write(m)
val mapper = new ObjectMapper()
mapper.writeValueAsString(Map("a" -> 1))
результат> {"empty": false, "traversableAgain": true}
==============================
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
mapper.writeValueAsString(Map("a" -> 1))
результат> {"a":1}
Вы должны сказать Джексону, как обращаться с объектами scala: mapper.registerModule(DefaultScalaModule)
val mymap = array.map {
case 1 => ("A", 1)
case 2 => ("B", 2)
case 3 => ("C", 3)
}
.toMap
С помощью scala.util.parsing.json.JSONObject
Вам нужна только 1 строка:
import scala.util.parsing.json.JSONObject
JSONObject(mymap).toString()
Если вы работаете с четко определенной моделью данных, почему бы не определить классы дел и не использовать макросы Play JSON для обработки преобразования? т.е.
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)
Используя библиотеку Джексона, вы можете использовать java-объект HashMap вместо Scala. Тогда вы можете использовать тот же код "безуспешно", который вы уже написали.
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)
возвращается
jstring: String = {"dog":4,"cat":1}
На случай, если кто-то ищет решение с использованием стандартных библиотек.
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
}
Следующий фрагмент, взятый с официального сайта Scala, мне подошел. Он использует библиотеку uPickle .
val map: Map[String, Int] =
Map("Toolkitty" -> 3, "Scaniel" -> 5)
val jsonString: String = upickle.default.write(map)
println(jsonString)
// prints: {"Toolkitty":3,"Scaniel":5}