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 bonnes façons existantes de générer et de désérialiser Json qui fonctionnent avec Scala 2.10.
Existe-t-il des méthodes recommandées pour le faire dans Scala 2.10?
Jackson est une bibliothèque Java pour traiter rapidement JSON. Le projet Jerkson enveloppe Jackson, mais semble abandonné. Je suis passé à Jackson Scala Module pour la sérialisation et la désérialisation vers les structures de données natives Scala.
Pour l'obtenir, incluez les éléments suivants dans votre build.sbt
:
libraryDependencies ++= Seq(
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.1.3",
...
)
Ensuite, vos exemples fonctionneront textuellement avec le wrapper Jackson suivant (je l'ai extrait des fichiers de test 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.erasure }
else new ParameterizedType {
def getRawType = m.erasure
def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
def getOwnerType = null
}
}
}
Autres Scala 2.10 Les options JSON incluent Twitter scala-json basé sur le livre de programmation Scala - c'est simple, au prix de Il y a aussi spray-json , qui utilise parboiled pour l'analyse. Enfin, la gestion JSON de Play a l'air sympa, mais il ne se dissocie pas facilement du projet Play.
Je peux chaleureusement recommander argonaut pour le support json dans scala. Tout ce dont vous avez besoin pour le configurer pour sérialiser votre objet Client est une ligne:
implicit lazy val CodecCustomer: CodecJson[Customer] =
casecodec6(Customer.apply, Customer.unapply)("id","name","address","city","state","user_id")
Cela soutiendra votre classe pour lui donner un .asJson
méthode qui le transforme en chaîne. Il va également pimp la classe de chaîne pour lui donner une méthode .decodeOption[List[Customer]]
pour analyser les chaînes. Il gère très bien les options de votre classe. Voici une classe ouvrière avec un test réussi et une méthode principale en cours d'exécution que vous pouvez déposer dans un clone git d'argonaute pour tout voir fonctionner correctement:
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 réactifs pour les gens qui commencent.
Il existe maintenant un fork de Jerkson qui prend en charge Scala 2.10 sur https://github.com/randhindi/jerkson .
Donc, sur la base de l'absence d'un message d'erreur et d'un exemple de code incorrect, je soupçonne que c'est plus un problème de ne pas comprendre comment fonctionne l'extraction lift-json. Si j'ai mal compris, faites des commentaires et faites-le moi savoir. Donc, si j'ai raison, voici ce dont vous avez besoin.
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
Ensuite, pour inverser le processus, vous feriez quelque chose comme:
// Person Json is a JValue here.
personJson.extract[Person]
Si ce n'est pas la partie avec laquelle vous avez des problèmes, faites-le moi savoir et je pourrai essayer de réviser ma réponse pour être plus utile.