37 votes

Scala 2.10 + sérialisation et désérialisation Json

Scala 2.10 semble avoir cassé certaines des anciennes bibliothèques (au moins pour le moment) comme Jerkson et lift-json.

La convivialité cible est la suivante:

 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)
 

Mais j'ai du mal à trouver de bons moyens existants pour générer et désérialiser Json qui fonctionnent avec Scala 2.10.

Existe-t-il des méthodes optimales pour ce faire dans Scala 2.10?

39voto

Kipton Barros Points 12445

Jackson est une bibliothèque Java pour traiter JSON rapide. Le Jerkson projet enveloppements Jackson, mais semble être abandonnée. J'ai passé à Jackson Scala Module pour la sérialisation et la désérialisation natif Scala structures de données.

Pour l'obtenir, inclure les éléments suivants dans votre build.sbt:

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

Ensuite, votre exemples de travail textuellement avec la suite de Jackson wrapper (j'ai extrait de jackson-module-scala fichiers de test):

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

D'autres Scala 2.10 JSON options comprennent Twitter de la scala-json basé sur la Programmation Scala livre-c'est simple, au détriment des performances. Il y a aussi de pulvérisation-json, qui utilise du riz étuvé pour l'analyse. Enfin, Jouer du JSON de manutention de l'air sympa, mais il n'est pas facile de dissocier de la pièce de projet.

7voto

Johan Prinsloo Points 1077

Mentionner json4s qui englobe jackson, lift-json ou sa propre implémentation native comme solution à long terme:

6voto

simbo1905 Points 911

Je peux vous recommander chaudement argonaut pour la prise en charge de json en scala. Tout ce que vous devez le configurer pour sérialiser vos Client de l'objet est une seule ligne:

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

Qui va pimp votre classe pour lui donner un .asJson méthode qui le transforme en une chaîne de caractères. Il sera également pimp la classe string pour lui donner une méthode .decodeOption[List[Customer]] analyser les chaînes. Il gère les options de votre classe d'amende. Ici, c'est un travail de classe avec un test de passage et une méthode main qui vous pouvez vous déplacer dans un git clone de argonaut de voir que tout fonctionne bien:

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

  }
}

Les développeurs sont également utiles et adaptés pour les gens de commencer.

4voto

Il existe maintenant un fork de Jerkson qui prend en charge Scala 2.10 sur https://github.com/randhindi/jerkson .

2voto

Matt F Points 556

Donc, basé sur l'absence d'un message d'erreur et le mauvais exemple de code, je suis soupçonner c'est plus une question de juste ne pas comprendre comment l'ascenseur-json extraction des œuvres. Si j'ai mal compris, de faire un commentaire et laissez-moi savoir. Donc, si je suis à droite, puis voici ce que vous devez.

Pour sérialiser:

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

implicit val formats = DefaultFormats

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

Puis d'inverser le processus, vous feriez quelque chose comme:

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

Si ce n'est pas la partie que vous êtes d'avoir des ennuis avec, alors faites-le moi savoir et je peux essayer de modifier ma réponse pour être plus utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X