什么JSON库在Scala中使用?
我需要build立一个JSONstring,如下所示:
[ { 'id': 1, 'name': 'John'}, { 'id': 2, 'name': 'Dani'} ] val jArray = JsArray(); jArray += (("id", "1"), ("name", "John")) jArray += (("id", "2"), ("name", "Dani")) println(jArray.dump)
我需要能够添加行到jArray
,就像jArray += ...
最接近的图书馆/解决scheme是什么?
不幸的是编写一个JSON库是Scala社区编写待办事项列表应用程序的版本。
有很多种select。 我列出他们没有特别的顺序,与笔记:
- parsing.json.JSON – 警告这个库只可用于Scala 2.9.x版(在新版本中删除)
- spray-json – 从Spray项目中提取
- Jerkson – – 警告一个很好的库(build立在Java Jackson之上),但现在放弃了。 如果你打算使用这个,可能按照Scalding项目的例子,并使用backchat.io分叉
- sjson – 由Debasish Ghosh
- lift-json – 可以与Lift项目分开使用
- json4s§ – 从lift-json中提取,试图创build其他JSON库可以使用的标准JSON AST。 包括jackson支持的实施
- Argonaut§ – 一个面向FP的面向Scala的JSON库,来自Scalaz背后的人
- play-json ± – 现在可以单独使用,请参阅此答案以了解详细信息
- 第戎 – 警告放弃。 一个dynamictypes的Scala JSON库
- sonofjson – 针对超级简单API的JSON库
- Jawn – Erik Osheim的JSON库旨在实现jackson或更快的速度
- Rapture JSON ± – 可以使用2,4,5,6,7,11或Jackson作为后端的JSON前端
- circe – build造在猫而不是scalaz之上的Argonaut的叉子
§=拥有Scalaz整合,±=支持与Jackson JsonNode
互操作
在Snowplow中,我们使用json4s与Jackson后端; 我们也和Argonaut有过很好的经历。
Lift-json的版本是2.6,它工作得非常好(也得到了很好的支持,维护人员随时准备修复用户可能遇到的任何错误,你可以在github存储库中find使用它的例子
维护人员(Joni Freeman)总是可以在Lift邮件列表上find。 邮件列表上还有其他用户也非常有帮助。
正如@Alexey所指出的那样,如果你想使用其他Scala版本的库,比如2.11.x
,改变scalaVersion
并使用%%
如下:
scalaVersion := "2.11.5" "net.liftweb" %% "lift-json" % "2.6"
随着时间的推移,您可以检查liftweb.net网站以查找最新版本。
我build议使用jerkson ,它支持最基本的types转换:
scala> import com.codahale.jerkson.Json._ scala> val l = List( Map( "id" -> 1, "name" -> "John" ), Map( "id" -> 2, "name" -> "Dani") ) scala> generate( l ) res1: String = [{"id":1,"name":"John"},{"id":2,"name":"Dani"}]
名单上的第7位是jackson,不使用jackson。 它支持Scala对象,(case类等)。
以下是我如何使用它的一个例子。
object MyJacksonMapper extends JacksonMapper val jsonString = MyJacksonMapper.serializeJson(myObject) val myNewObject = MyJacksonMapper.deserializeJson[MyCaseClass](jsonString)
这使得它非常简单。 另外就是XmlSerializer和对JAXB Annotations的支持非常方便。
这篇博客文章描述了它与JAXB注释和Play框架一起使用。
http://krasserm.blogspot.co.uk/2012/02/using-jaxb-for-xml-and-json-apis-in.html
这是我目前的JacksonMapper。
trait JacksonMapper { def jsonSerializer = { val m = new ObjectMapper() m.registerModule(DefaultScalaModule) m } def xmlSerializer = { val m = new XmlMapper() m.registerModule(DefaultScalaModule) m } def deserializeJson[T: Manifest](value: String): T = jsonSerializer.readValue(value, typeReference[T]) def serializeJson(value: Any) = jsonSerializer.writerWithDefaultPrettyPrinter().writeValueAsString(value) def deserializeXml[T: Manifest](value: String): T = xmlSerializer.readValue(value, typeReference[T]) def serializeXml(value: Any) = xmlSerializer.writeValueAsString(value) private[this] def typeReference[T: Manifest] = new TypeReference[T] { override def getType = typeFromManifest(manifest[T]) } private[this] def typeFromManifest(m: Manifest[_]): Type = { if (m.typeArguments.isEmpty) { m.erasure } else new ParameterizedType { def getRawType = m.erasure def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray def getOwnerType = null } } }
也许我晚了一点,但你真的应该尝试从播放框架使用json库。 你可以看看文档 。 在当前的2.1.1版本中,你不能单独使用它,所以依赖关系看起来像这样:
val typesaferepo = "TypeSafe Repo" at "http://repo.typesafe.com/typesafe/releases" val play2 = "play" %% "play" % "2.1.1"
它将为您带来全面的游戏框架。
但据我所知,来自Typesafe的人有计划在2.2版本中将其分开。 所以,2.2快照中有独立的play-json 。
这是一个使用json4s
编写然后阅读json
文件的基本实现。
import org.json4s._ import org.json4s.jackson.JsonMethods._ import org.json4s.JsonDSL._ import java.io._ import scala.io.Source object MyObject { def main(args: Array[String]) { val myMap = Map("a" -> List(3,4), "b" -> List(7,8)) // writing a file val jsonString = pretty(render(myMap)) val pw = new PrintWriter(new File("my_json.json")) pw.write(jsonString) pw.close() // reading a file val myString = Source.fromFile("my_json.json").mkString println(myString) val myJSON = parse(myString) println(myJSON) // Converting from JOjbect to plain object implicit val formats = DefaultFormats val myOldMap = myJSON.extract[Map[String, List[Int]]] println(myOldMap) } }
Jawn是Scala中非常灵活的JSONparsing器库。 它也允许生成自定义的AST; 你只需要提供一个小的特点映射到AST。
对于需要一点点JSONparsing的最近项目来说,效果很好。
你应该检查Genson 。 它只是起作用,并且比Scala中大多数现有的替代品更容易使用。 它速度快,有许多function,并与其他一些库(jodatime,json4s DOM api …)集成。
所有那些没有任何花哨的不必要的代码像implicits,定制读者/作家的基本情况下,ilisible API由于运营商过载…
使用它是一样简单的:
import com.owlike.genson.defaultGenson_ val json = toJson(Person(Some("foo"), 99)) val person = fromJson[Person]("""{"name": "foo", "age": 99}""") case class Person(name: Option[String], age: Int)
免责声明:我是Gensons作者,但这并不代表我不客观:)
@ AlaxDean的#7答案, Argonaut是唯一一个能够迅速与sbt和intellij合作的人。 其实json4s也花了很less的时间,但处理一个原始的AST不是我想要的。 通过在我的build.st中放入一行代码,我得到了argonaut的工作:
libraryDependencies += "io.argonaut" %% "argonaut" % "6.0.1"
然后进行一个简单的testing,看看是否可以得到JSON:
package mytest import scalaz._, Scalaz._ import argonaut._, Argonaut._ object Mytest extends App { val requestJson = """ { "userid": "1" } """.stripMargin val updatedJson: Option[Json] = for { parsed <- requestJson.parseOption } yield ("name", jString("testuser")) ->: parsed val obj = updatedJson.get.obj printf("Updated user: %s\n", updatedJson.toString()) printf("obj : %s\n", obj.toString()) printf("userid: %s\n", obj.get.toMap("userid")) }
接着
$ sbt > run Updated user: Some({"userid":"1","name":"testuser"}) obj : Some(object[("userid","1"),("name","testuser")]) userid: "1"
确保你熟悉的选项 ,这只是一个值,也可以为空(我猜是无效的)。 Argonaut使用Scalaz,所以如果你看到一些你不明白的东西,比如符号\/
(an或者operation),那很可能是Scalaz。
在答案的列表中似乎没有被提及。 它可以从http://rapture.io/获得,并允许您(除其他外):;
- selectJSON后端,这是非常有用的,如果你已经使用一个(在导入)
- 决定是否使用Try,Future,Option,Either等(也在导入中)
- 在一行代码中做很多工作。
我不想从它的页面复制/粘贴Rapture示例。 Jon Pretty在SBTB 2014上发表了关于Rapturefunction的精彩演讲: https : //www.youtube.com/watch?v= ka5-OLJgybI
你可以试试这个: https : //github.com/momodi/Json4Scala
这很简单,只有一个不到300行代码的scala文件。
有样品:
test("base") { assert(Json.parse("123").asInt == 123) assert(Json.parse("-123").asInt == -123) assert(Json.parse("111111111111111").asLong == 111111111111111l) assert(Json.parse("true").asBoolean == true) assert(Json.parse("false").asBoolean == false) assert(Json.parse("123.123").asDouble == 123.123) assert(Json.parse("\"aaa\"").asString == "aaa") assert(Json.parse("\"aaa\"").write() == "\"aaa\"") val json = Json.Value(Map("a" -> Array(1,2,3), "b" -> Array(4, 5, 6))) assert(json("a")(0).asInt == 1) assert(json("b")(1).asInt == 5) } test("parse base") { val str = """ {"int":-123, "long": 111111111111111, "string":"asdf", "bool_true": true, "foo":"foo", "bool_false": false} """ val json = Json.parse(str) assert(json.asMap("int").asInt == -123) assert(json.asMap("long").asLong == 111111111111111l) assert(json.asMap("string").asString == "asdf") assert(json.asMap("bool_true").asBoolean == true) assert(json.asMap("bool_false").asBoolean == false) println(json.write()) assert(json.write().length > 0) } test("parse obj") { val str = """ {"asdf":[1,2,4,{"bbb":"ttt"},432]} """ val json = Json.parse(str) assert(json.asMap("asdf").asArray(0).asInt == 1) assert(json.asMap("asdf").asArray(3).asMap("bbb").asString == "ttt") } test("parse array") { val str = """ [1,2,3,4,{"a":[1,2,3]}] """ val json = Json.parse(str) assert(json.asArray(0).asInt == 1) assert(json(4)("a")(2).asInt == 3) assert(json(4)("a")(2).isInt) assert(json(4)("a").isArray) assert(json(4)("a").isMap == false) } test("real") { val str = "{\"styles\":[214776380871671808,214783111085424640,214851869216866304,214829406537908224],\"group\":100,\"name\":\"AO4614【金macros达电子】现货库存 质量保证 欢迎购买@\",\"shopgrade\":8,\"price\":0.59,\"shop_id\":60095469,\"C3\":50018869,\"C2\":50024099,\"C1\":50008090,\"imguri\":\"http://img.geilicdn.com/taobao10000177139_425x360.jpg\",\"cag\":50006523,\"soldout\":0,\"C4\":50006523}" val json = Json.parse(str) println(json.write()) assert(json.asMap.size > 0) }
我使用PLAY JSON库,您可以在这里find仅用于JSON库的mavn库,而不是整个框架
val json = "com.typesafe.play" %% "play-json" % version val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"
有关如何使用它们的非常好的教程可以在这里find:
http://mandubian.com/2012/09/08/unveiling-play-2-dot-1-json-api-part1-jspath-reads-combinators/
http://mandubian.com/2012/10/01/unveiling-play-2-dot-1-json-api-part2-writes-format-combinators/
http://mandubian.com/2012/10/29/unveiling-play-2-dot-1-json-api-part3-json-transformers/
让我也给你JSON版本的SON :
import nl.typeset.sonofjson._ arr( obj(id = 1, name = "John) obj(id = 2, name = "Dani) )
Play独立于Play Framework发布了用于处理JSON的模块, Play WS
做了一个关于这个博客文章,请查看http://pedrorijo.com/blog/scala-json/
使用案例类和Play WS (已包含在Play Framework中),您可以使用简单的单行隐式方法在json和case类之间进行转换
case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean) object User { implicit val userJsonFormat = Json.format[User] }
我使用uPickle ,它具有自动处理嵌套大小类的巨大优势:
object SerializingApp extends App { case class Person(name: String, address: Address) case class Address(street: String, town: String, zipCode: String) import upickle.default._ val john = Person("John Doe", Address("Elm Street 1", "Springfield", "ABC123")) val johnAsJson = write(john) // Prints {"name":"John Doe","address":{"street":"Elm Street 1","town":"Springfield","zipCode":"ABC123"}} Console.println(johnAsJson) // Parse the JSON back into a Scala object Console.println(read[Person](johnAsJson)) }
添加到您的build.sbt
使用uPickle:
libraryDependencies += "com.lihaoyi" %% "upickle" % "0.4.3"