比如有一个复杂对象:
Map[Int, Map[Int, Double]]
需要将其转为JSON保存,之后再读取使用,试了几种方法,最后的方案是:
1、定义case class
2、所有的数据类型都转为String(避免不必要的麻烦,至少Map的key都要为String,不然会报错scala.MatchError)
3、Map必须是immutable.Map
代码如下
1、转json
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization._
import org.json4s.jackson.Serialization
case class WOE(col: String, woe: Map[String, String])
implicit val formats = Serialization.formats(NoTypeHints)
val testMap = Map[String, String]()
testMap += ("1" -> "1.1")
val a = WOE("1", immutable.Map(testMap.toList:_*))
println(write(a))
输出{"col":"1","woe":{"1":"1.1"}}
2、解析json
implicit val formats = Serialization.formats(NoTypeHints)
val js =
"""
{"col":"1","woe":{"1":"1.1"}}
"""
val ab = parse(js).extract[WOE]
println(write(ab))
如果是List也可以
implicit val formats = Serialization.formats(NoTypeHints)
val b = new ListBuffer[WOE]
val testMap = Map[String, String]()
testMap += ("1" -> "1.1")
b += WOE("1", immutable.Map(testMap.toList:_*))
b += WOE("3", immutable.Map(testMap.toList:_*))
println(write(b))
val js =
"""
[{"col":"1","woe":{"1":"1.1"}},{"col":"3","woe":{"1":"1.1"}}]
"""
val ab = parse(js).extract[List[WOE]]
println(ab.toString)
之前整理的一些方法
1、scala自带的Json解析
scala 2.10(以上,其他版本不清楚)自带Json解析,scala.util.parsing.json.JSON
object转json
val testMap = Map[String, String]()
testMap += ("1" -> "2.034")
testMap += ("2" -> "2.0134")
println(scala.util.parsing.json.JSONObject(scala.collection.immutable.Map(testMap.toList: _*)))
但好像只能处理map,且map要转成immutable
2、fastjson
解析json
import com.alibaba.fastjson.JSON
object JsonDemo {
def main(args: Array[String]) {
val text = "{\"name\":\"name1\", \"age\":55}"
val json = JSON.parseObject(text)
println(json.get("name"))
println(json.get("age"))
}
}
再例如
import com.alibaba.fastjson.JSON
object Json {
def main(args: Array[String]): Unit = {
val str2 = "{\"et\":\"kanqiu_client_join\",\"vtm\":1435898329434,\"body\":{\"client\":\"866963024862254\",\"client_type\":\"android\",\"room\":\"NBA_HOME\",\"gid\":\"\",\"type\":\"\",\"roomid\":\"\"},\"time\":1435898329}"
val json=JSON.parseObject(str2)
//获取成员
val fet=json.get("et")
//返回字符串成员
val etString=json.getString("et")
//返回整形成员
val vtm=json.getInteger("vtm")
println(vtm)
//返回多级成员
val client=json.getJSONObject("body").get("client")
println(client)
在spark-steaming中,使用fast-json更加稳定,json-lib经常出现莫名问题,而且fastjson的解析速度更快.
object转json,首先必须要显式的定义参数,否则会报错
ambiguous reference to overloaded definition
例如:
val testMap = Map[String, String]()
testMap += ("1" -> "2.034")
testMap += ("2" -> "2.0134")
val a = JSON.toJSONString(testMap, true)
println(a)
不会报错,但是输出结果是奇怪的
{
"empty":false,
"sizeMapDefined":false,
"traversableAgain":true
}
3、json4s
object转json
val testMap = Map[String, String]()
testMap += ("1" -> "2.034")
testMap += ("2" -> "2.0134")
val jj = compact(render(testMap))
println(jj)
输出
[{"2":"2.0134"},{"1":"2.034"}]
如果都是String,复杂的Map结构也可以解析
val testMap = Map[String, Map[String, String]]()
val subMap = Map[String, String]()
subMap += ("1" -> "1.1")
testMap += ("1" -> subMap)
println(write(testMap))
输出{"1":{"1":"1.1"}}
但这样的形式不利于解析
再例如
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)))
val mm = Map(
"1" -> Map ("1"->"1.2")
)
println(write(a))