Scala 2.10 + Json 序列化和反序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12591457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:33:31  来源:igfitidea点击:

Scala 2.10 + Json serialization and deserialization

jsonscalascala-2.10lift-json

提问by user1698607

Scala 2.10 seems to have broken some of the old libraries (at least for the time being) like Jerkson and lift-json.

Scala 2.10 似乎已经破坏了一些旧库(至少目前是这样),例如 Jerkson 和lift-json。

The target usability is as follows:

目标可用性如下:

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)

But I'm having trouble finding good existing ways of generating and deserializing Json that work with Scala 2.10.

但是我很难找到生成和反序列化适用于 Scala 2.10 的 Json 的良好现有方法。

Are there best practice ways of doing this in Scala 2.10?

在 Scala 2.10 中有这样做的最佳实践方法吗?

回答by Kipton Barros

Hymansonis a Java library to process JSON fast. The Jerkson project wraps Hymanson, but appears to be abandoned. I've switched to Hymanson's Scala Modulefor serialization and deserialization to native Scala data structures.

Hymanson是一个用于快速处理 JSON 的 Java 库。Hyman森项目包装了Hyman逊,但似乎被放弃了。我已经切换到 Hymanson 的Scala 模块,用于对原生 Scala 数据结构进行序列化和反序列化。

To get it, include the following in your build.sbt:

要获得它,请在您的build.sbt:

libraryDependencies ++= Seq(
  "com.fasterxml.Hymanson.module" %% "Hymanson-module-scala" % "2.1.3",
   ...
)

Then your examples will work verbatim with the following Hymanson wrapper (I extracted it from Hymanson-module-scala test files):

然后,您的示例将使用以下 Hymanson 包装器逐字运行(我从 Hymanson-module-scala 测试文件中提取了它):

import java.lang.reflect.{Type, ParameterizedType}
import com.fasterxml.Hymanson.databind.ObjectMapper
import com.fasterxml.Hymanson.module.scala.DefaultScalaModule
import com.fasterxml.Hymanson.annotation.JsonProperty;
import com.fasterxml.Hymanson.core.`type`.TypeReference;

object HymansonWrapper {
  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.erasure }
    else new ParameterizedType {
      def getRawType = m.erasure
      def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
      def getOwnerType = null
    }
  }
}

Other Scala 2.10 JSON options include Twitter's scala-jsonbased on the Programming Scala book--it's simple, at the cost of performance. There is also spray-json, which uses parboiledfor parsing. Finally, Play's JSON handlinglooks nice, but it does not easily decouple from the Play project.

其他 Scala 2.10 JSON 选项包括 Twitter 的基于 Scala 编程书籍的scala-json——它很简单,但以性能为代价。还有Spray-json,它使用parboiled进行解析。最后,Play 的 JSON 处理看起来不错,但它并不容易与 Play 项目分离。

回答by Johan Prinsloo

Mentioning json4sthat wraps Hymanson, lift-json or its own native implementation as a long term solution:

提到包装 Hymanson、lift-json 或其自己的本机实现的json4s作为长期解决方案:

回答by simbo1905

I can heartily recommend argonautfor json support in scala. All you need to configure it to serialize your Customer object is one line:

我可以衷心推荐argonaut在 Scala 中提供 json 支持。配置它以序列化 Customer 对象所需的全部内容是一行:

implicit lazy val CodecCustomer: CodecJson[Customer] =
casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")

That will pimp your class to give it an .asJsonmethod which turns it into a string. It will also pimp the string class to give it a method .decodeOption[List[Customer]]to parse strings. It handles the options in your class fine. Here is a working class with a passing test and a running main method which you can drop into a git clone of argonaut to see it all working fine:

这将拉皮条你的班级给它一个.asJson方法,把它变成一个字符串。它还将对字符串类进行拉皮条,为其提供.decodeOption[List[Customer]]解析字符串的方法。它可以很好地处理您班级中的选项。这是一个通过测试和正在运行的 main 方法的工作类,您可以将其放入 argonaut 的 git clone 中以查看它是否正常工作:

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}")

  }
}

The developers are also helpful and responsive to folks getting started.

开发人员也乐于助人,并且对人们的入门做出回应。

回答by Sebastian Ganslandt

There is now a fork of Jerkson that supports Scala 2.10 at https://github.com/randhindi/jerkson.

现在在https://github.com/randhindi/jerkson有一个支持 Scala 2.10 的 Jerkson 分支。

回答by Matt Farmer

So, based on the absence of an error message and the incorrect sample code, I'm suspecting this is more of an issue of just not understanding how the lift-json extraction works. If I've misunderstood, do comment and let me know. So, if I'm right then here's what you need.

因此,基于没有错误消息和不正确的示例代码,我怀疑这更多是一个不了解 Lift-json 提取如何工作的问题。如果我误解了,请发表评论并让我知道。所以,如果我是对的,那么这就是你需要的。

To serialize:

序列化:

import net.liftweb.json._
  import Extraction._

implicit val formats = DefaultFormats

case class Person(...)
val person = Person(...)
val personJson = decompose(person) // Results in a JValue

Then to reverse the process you'd do something like:

然后要反转该过程,您可以执行以下操作:

// Person Json is a JValue here.
personJson.extract[Person]

If that's not the part you're having trouble with, then do let me know and I can try to revise my answer to be more helpful.

如果这不是您遇到问题的部分,请告诉我,我可以尝试修改我的答案以提供更多帮助。