【问题标题】:How to convert Scala Map into JSON String?如何将 Scala Map 转换为 JSON 字符串?
【发布时间】:2015-03-12 22:37:41
【问题描述】:

例如,我在 Scala 中有这个 Map 值:

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 框架 v2.3,但该解决方案不需要使用 Play JSON 库,但如果有人可以同时提供 Play 和非 Play 解决方案,那就太好了。

这是我迄今为止所做的没有成功:

// using jackson library
val mapper = new ObjectMapper()
val res = mapper.writeValueAsString(m)
println(res)

结果:

{"empty":false,"traversableAgain":true}

我不明白为什么我会得到这个结果。

【问题讨论】:

    标签: json scala playframework playframework-2.0


    【解决方案1】:

    作为非播放解决方案,您可以考虑使用json4s,它提供了对jackson 的封装并且易于使用。 如果您使用的是 json4s,那么您可以使用以下方法将 map 转换为 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)
    

    【讨论】:

    • 嗨,mohit,愿意提供完整的代码示例吗?如果我只写write(m),我会得到not found 编译错误。
    • @suud - 已更新。在 sbt 中为 jackson 添加 json4s 依赖后,它将起作用。
    • 您的代码在我尝试时不起作用,因为我使用来自Json4s 的 Lift Json 版本,导入不同。我已经知道如何解决它,但我会给你一个包装答案的机会:)
    • @suud - 我已经更改了导入。我猜不会有更多的变化。无论如何,如果有任何更改,您为什么不继续编辑答案,以便将来对其寻找类似内容的其他人有所帮助:)
    • @suud 我不完全确定。两者都告诉 json4s 如何序列化/反序列化。当我希望 json4s 处理所有内容时,我不使用类型提示,而当我想要覆盖某些字段(如日期时间格式)时使用 defaultFormats
    【解决方案2】:
    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}

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
    • 您应该创建新对象。例如 mapper.registerModule(new DefaultScalaModule())
    【解决方案3】:

    你需要告诉jackson如何处理scala对象:mapper.registerModule(DefaultScalaModule)

    【讨论】:

    • 我得到编译错误:DefaultScalaModule 未找到。我google了一下,发现我必须添加import com.fasterxml.jackson.module.scala.DefaultScalaModule,但是找不到这个类。
    • 您可以从通常的地方下载它。喜欢here
    • libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala" % "2.4.4"
    • 我也遇到了同样的错误。修复是 mapper.registerModule(new DefaultScalaModule())
    【解决方案4】:
    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()
    

    【讨论】:

    • 注意,它不会递归,并且会将嵌套对象转换为它们的字符串表示形式!
    • 此外,它已被弃用(使用 Scala 2.11.12)。我现在没有做需要我担心的事情,但我想我会提到它。
    【解决方案5】:

    如果您使用的是定义明确的数据模型,为什么不定义案例类并使用 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)
    

    【讨论】:

    • 您好,感谢您提供的信息。就我而言,没有涉及 POJO(或者可能是 POSO)。
    【解决方案6】:

    使用 Jackson 库可以做的一件事是使用 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}    
    

    【讨论】:

    • 在scala代码中使用java类就scala的好习惯而言可以吗?
    • 在 scala 中使用 java 对象时,我建议不要在代码顶部导入,而是像示例中那样实例化 java 对象:“val jmap = new java.util.HashMap(...) " 等等。这样你的命名空间就不会在 java 和 scala 类型之间混淆。
    【解决方案7】:

    如果有人正在寻找使用标准库的解决方案。

    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
    }
    

    【讨论】:

    • 当字符串包含反斜杠或文字引号时会发生什么?
    猜你喜欢
    • 2019-08-25
    • 2015-07-06
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多