我需要构建一个JSON字符串,如下所示:
[
{ '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 += ...
最近的图书馆/解决方案是什么?
答案 0 :(得分:197)
不幸的是,编写JSON库是Scala社区编写todo列表应用程序的版本。
有很多种选择。我没有特别的顺序列出它们,附注:
§=有Scalaz整合,±=支持与杰克逊JsonNode
的互操作
在Snowplow中,我们使用json4s和Jackson后端;我们也和Argonaut有过很好的经历。
答案 1 :(得分:17)
Lift-json版本为2.6,它运行得非常好(并且也得到很好的支持,维护者随时准备修复用户可能发现的任何错误。 您可以在github repository
上找到使用它的示例Lift mailing列表上始终可以访问维护者(Joni Freeman)。邮件列表中还有其他用户也非常有帮助。
正如@Alexey指出的那样,如果您想将该库与其他Scala版本一起使用,请说2.11.x
,请更改scalaVersion
并使用%%
,如下所示:
scalaVersion := "2.11.5"
"net.liftweb" %% "lift-json" % "2.6"
您可以查看liftweb.net网站,了解随时间推移的最新版本。
答案 2 :(得分:15)
我建议使用jerkson,它支持大多数基本类型转换:
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"}]
答案 3 :(得分:10)
名单上的第7名是杰克逊,而不是使用杰克逊。它支持Scala对象(案例类等)。
以下是我如何使用它的示例。
object MyJacksonMapper extends JacksonMapper
val jsonString = MyJacksonMapper.serializeJson(myObject)
val myNewObject = MyJacksonMapper.deserializeJson[MyCaseClass](jsonString)
这使得它非常简单。另外,XmlSerializer和对JAXB Annotations的支持非常方便。
此博客文章描述了它与JAXB Annotations和Play Framework一起使用。
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
}
}
}
答案 4 :(得分:8)
也许我迟到了,但你真的应该尝试使用play框架中的json库。 你可以看看documentation。在当前的2.1.1版本中,如果没有完整游戏2,则无法单独使用它,因此依赖关系将如下所示:
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。
答案 5 :(得分:5)
您应该检查Genson。 它只是工作,并且比Scala中的大多数现有替代品更容易使用。它很快,具有许多功能并与其他一些库集成(jodatime,json4s DOM api ...)。
所有没有任何花哨的不必要的代码,如implicits,基本案例的自定义读者/编写者,由于操作员超载导致的错误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的作者,但那并不是我不客观的。)
答案 6 :(得分:5)
以下是使用json
编写然后阅读json4s
文件的基本实现。
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)
}
}
答案 7 :(得分:4)
Jawn是Scala中非常灵活的JSON解析器库。它还允许生成自定义AST;你只需要提供一个小的特征来映射到AST。
非常适合最近需要进行一些JSON解析的项目。
答案 8 :(得分:4)
Rapture似乎在答案列表中缺失。 它可以从http://rapture.io/获得,并允许您(除其他事项外):
我不想在其页面上复制/粘贴Rapture示例。关于Rapture的一些很好的演示由Jon Pretty在SBTB 2014上发表:https://www.youtube.com/watch?v=ka5-OLJgybI
答案 9 :(得分:3)
@ AlaxDean的#7答案,Argonaut是唯一能够与sbt和intellij一起快速工作的人。实际上json4s也花了很少的时间,但处理原始AST不是我想要的。我让argonaut通过在我的build.st中添加一行来工作:
libraryDependencies += "io.argonaut" %% "argonaut" % "6.0.1"
然后进行一个简单的测试,看看我是否可以获得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"
确保您熟悉Option,这只是一个也可以为null的值(我猜是空的安全)。 Argonaut使用Scalaz所以如果你看到一些你不理解的东西,比如符号\/
(一个或一个操作),它可能就是Scalaz。
答案 10 :(得分:2)
你可以试试这个: https://github.com/momodi/Json4Scala
这很简单,只有一个scala文件,代码少于300行。
有样品:
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【金宏达电子】现货库存 质量保证 欢迎购买@\",\"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)
}
答案 11 :(得分:0)
我使用PLAY JSON库 你可以找到只有JSON库的mavn repo而不是整个框架
val json = "com.typesafe.play" %% "play-json" % version
val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"
有关如何使用它们的非常好的教程,请点击此处:
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/
答案 12 :(得分:0)
我还要提供SON of JSON版本:
import nl.typeset.sonofjson._
arr(
obj(id = 1, name = "John)
obj(id = 2, name = "Dani)
)
答案 13 :(得分:0)
Play发布了独立于Play Framework处理JSON的模块,Play WS
发表关于此事的博客文章,请在http://pedrorijo.com/blog/scala-json/
查看使用案例类和Play WS(已包含在Play框架中),您可以在json和case类之间进行转换,并使用简单的单行隐式
case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)
object User {
implicit val userJsonFormat = Json.format[User]
}
答案 14 :(得分:0)
我使用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"