Scala 2.10似乎已经破坏了一些旧库(至少目前是这样),如Jerkson和lift-json。
目标可用性如下:
case class Person(name: String, height: String, attributes: Map[String, String], friends: List[String])
//to serialize
val person = Person("Name", ....)
val json = serialize(person)
//to deserialize
val sameperson = deserialize[Person](json)
但是我很难找到与 Scala 2.10 一起使用的生成和反序列化 Json 的现有方法。
在 Scala 2.10 中是否有执行此操作的最佳实践方法?
Jackson 是一个快速处理 JSON 的 Java 库。Jerkson项目包裹了杰克逊,但似乎被放弃了。我已经切换到杰克逊的 Scala 模块进行序列化和反序列化到本机 Scala 数据结构。
要获取它,请在您的build.sbt
中包含以下内容:
libraryDependencies ++= Seq(
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.1.3",
...
)
然后,您的示例将逐字处理以下 Jackson 包装器(我从 jackson-module-scala 测试文件中提取了它):
import java.lang.reflect.{Type, ParameterizedType}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.`type`.TypeReference;
object JacksonWrapper {
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
def serialize(value: Any): String = {
import java.io.StringWriter
val writer = new StringWriter()
mapper.writeValue(writer, value)
writer.toString
}
def deserialize[T: Manifest](value: String) : T =
mapper.readValue(value, typeReference[T])
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.runtimeClass }
else new ParameterizedType {
def getRawType = m.runtimeClass
def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
def getOwnerType = null
}
}
}
其他Scala 2.10 JSON选项包括Twitter基于Programming Scala书的scala-json,这很简单,但以性能为代价。还有spray-json,它使用parboiled进行解析。最后,Play的JSON处理看起来不错,但它不容易与Play项目分离。
jackson、lift-json 或其自己的原生实现包装为长期解决方案的 json4:
- 法典
- 网站
我可以衷心推荐argonaut在scala中支持json。只需一行即可将其配置为序列化 Customer 对象:
implicit lazy val CodecCustomer: CodecJson[Customer] =
casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")
这将为您的类提供一个.asJson
方法,将其转换为字符串。它还将皮条客字符串类,为其提供.decodeOption[List[Customer]]
解析字符串的方法。它可以很好地处理类中的选项。这是一个具有通过测试和运行 main 方法的工人类,您可以将其放入 argonaut 的 git 克隆中以查看其正常工作:
package argonaut.example
import org.specs2.{ScalaCheck, Specification}
import argonaut.CodecJson
import argonaut.Argonaut._
case class Customer(id: Int, name: String, address: Option[String],
city: Option[String], state: Option[String], user_id: Int)
class CustomerExample extends Specification with ScalaCheck {
import CustomerExample.CodecCustomer
import CustomerExample.customers
def is = "Stackoverflow question 12591457 example" ^
"round trip customers to and from json strings " ! {
customers.asJson.as[List[Customer]].toOption must beSome(customers)
}
}
object CustomerExample {
implicit lazy val CodecCustomer: CodecJson[Customer] =
casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")
val customers = List(
Customer(1,"one",Some("one street"),Some("one city"),Some("one state"),1)
, Customer(2,"two",None,Some("two city"),Some("two state"),2)
, Customer(3,"three",Some("three address"),None,Some("three state"),3)
, Customer(4,"four",Some("four address"),Some("four city"),None,4)
)
def main(args: Array[String]): Unit = {
println(s"Customers converted into json string:n ${customers.asJson}")
val jsonString =
"""[
| {"city":"one city","name":"one","state":"one state","user_id":1,"id":1,"address":"one street"}
| ,{"city":"two city","name":"two","state":"two state","user_id":2,"id":2}
| ,{"name":"three","state":"three state","user_id":3,"id":3,"address":"three address"}
| ,{"city":"four city","name":"four","user_id":4,"id":4,"address":"four address"}
|]""".stripMargin
var parsed: Option[List[Customer]] = jsonString.decodeOption[List[Customer]]
println(s"Json string turned back into customers:n ${parsed.get}")
}
}
开发人员对入门人员也很有帮助和响应。
现在有一个 Jerkson 的分支,在 https://github.com/randhindi/jerkson 支持 Scala 2.10。
因此,基于没有错误消息和不正确的示例代码,我怀疑这更像是一个不了解 lift-json 提取如何工作的问题。如果我误解了,请发表评论并告诉我。所以,如果我是对的,那么这就是你需要的。
序列化:
import net.liftweb.json._
import Extraction._
implicit val formats = DefaultFormats
case class Person(...)
val person = Person(...)
val personJson = decompose(person) // Results in a JValue
然后,要逆转该过程,您可以执行以下操作:
// Person Json is a JValue here.
personJson.extract[Person]
如果这不是您遇到问题的部分,请告诉我,我可以尝试修改我的答案以提供更多帮助。