Comment construire et parsingr une chaîne JSON dans Scala / Lift

Je tente d’utiliser JSON pour envoyer des données entre le navigateur et mon application.

Je tente d’utiliser Lift 1.0 pour créer et parsingr des chaînes JSON, mais pour une raison quelconque, je ne parviens pas à parsingr le JSON que je viens de construire:

scala>import scala.util.parsing.json.JSON._ import scala.util.parsing.json.JSON._ scala> import net.liftweb.http.js._ import net.liftweb.http.js._ scala> import net.liftweb.http.js.JE._ import net.liftweb.http.js.JE._ scala> val json = JsObj(("foo", 4), ("bar", "baz")).toJsCmd json: Ssortingng = {'foo': 4, 'bar': 'baz'} scala> parseFull(json) res3: Option[Any] = None 

Comment puis-je créer par programme un message JSON valide dans Scala / Lift pouvant également être analysé à nouveau?

Vous utilisez JsCmd Lift 1.0, qui produit JSON avec des chaînes entre guillemets simples et tente de l’parsingr avec l’parsingur de scala, qui ne prend en charge que les chaînes entre guillemets.

Il est important de comprendre qu’il existe plusieurs définitions pour JSON.

Les guillemets simples sont-ils valides dans JSON?

  • Ils sont selon ECMAScript 5th Ed
  • Ils ne sont pas conformes à la RFC 4627 originale de Crockford

Lift et Scala offrent de nombreux moyens d’parsingr JSON, parfois avec des comportements différents selon les versions.

Les chaînes acceptées par ces parsingurs ne sont pas équivalentes.

Voici quelques commentaires et exemples des différentes méthodes de création et d’parsing des chaînes JSON.


Produire JSON avec la bibliothèque lift-json DSL

  • conseillé
  • Malgré son nom, il s’agit d’un projet distinct sans aucune dépendance vis-à-vis du rest de Lift.

Exemple:

 scala> import net.liftweb.json.JsonAST import net.liftweb.json.JsonAST scala> import net.liftweb.json.JsonDSL._ import net.liftweb.json.JsonDSL._ scala> import net.liftweb.json.Printer._ import net.liftweb.json.Printer._ scala> val json1 = ("foo" -> 4) ~ ("bar" -> "baz") json1: net.liftweb.json.JsonAST.JObject = JObject(List(JField(foo,JInt(4)), JField(bar,JSsortingng(baz)))) scala> compact(JsonAST.render(json1)) res0: Ssortingng = {"foo":4,"bar":"baz"} scala> val json2 = List(1,2,3) json2: List[Int] = List(1, 2, 3) scala> compact(JsonAST.render(json2)) res1: Ssortingng = [1,2,3] scala> val json3 = ("foo", 4) ~ ("bar", List(1,2,3)) json3: net.liftweb.json.JsonAST.JObject = JObject(List(JField(foo,JInt(4)), JField(bar,JArray(List(JInt(1), JInt(2), JInt(3)))))) scala> compact(JsonAST.render(json3)) res2: Ssortingng = {"foo":4,"bar":[1,2,3]} 

Analyse JSON avec la bibliothèque lift-json

  • conseillé
  • Fournit un mappage implicite vers / depuis des classes de cas de scala
  • Les classes de cas définies dans la console ne sont pas sockets en charge pour le moment ( com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes une com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes )
  • L’exemple ci-dessous utilise PublicID , une classe de cas pré-existante afin qu’elle fonctionne sur la console Scala.

Exemple:

 scala> import scala.xml.dtd.PublicID import scala.xml.dtd.PublicID scala> import net.liftweb.json._ import net.liftweb.json._ scala> import net.liftweb.json.JsonAST._ import net.liftweb.json.JsonAST._ scala> import net.liftweb.json.JsonDSL._ import net.liftweb.json.JsonDSL._ scala> implicit val formats = DefaultFormats formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@7fa27edd scala> val jsonAst = ("publicId1" -> "idSsortingng") ~ ("systemId" -> "systemIdStr") jsonAst: net.liftweb.json.JsonAST.JObject = JObject(List(JField(publicId,JSsortingng(idSsortingng)), JField(systemId,JSsortingng(systemIdStr)))) scala> jsonAst.extract[PublicID] res0: scala.xml.dtd.PublicID = PUBLIC "idSsortingng" "systemIdStr" 

Analyse JSON dans Scala 2.7.7 et 2.8.1

  • Non recommandé – ” Plus vraiment pris en charge ”
  • L’parsingur de Scala 2.7.7 n’parsingra pas JSON
  • Cette méthode d’parsing utilisée dans la question

Exemple:

 scala>import scala.util.parsing.json.JSON._ import scala.util.parsing.json.JSON._ scala> parseFull("{\"foo\" : 4 }") res1: Option[Any] = Some(Map(foo -> 4.0)) scala> parseFull("[ 1,2,3 ]") res2: Option[Any] = Some(List(1.0, 2.0, 3.0)) scala> parseFull("{'foo' : 4 }") res3: Option[Any] = None 

Analyse JSON dans Lift 2.0 et 2.2 avec util.JSONParser

  • Recommandation neutre
  • Le util.JSONParser de Lift parsingra les chaînes JSON entre guillemets simples et doubles:

Exemple:

 scala> import net.liftweb.util.JSONParser._ import net.liftweb.util.JSONParser._ scala> parse("{\"foo\" : 4 }") res1: net.liftweb.common.Box[Any] = Full(Map(foo -> 4.0)) scala> parse("[ 1,2,3 ]") res2: net.liftweb.common.Box[Any] = Full(List(1.0, 2.0, 3.0)) scala> parse("{'foo' : 4}") res3: net.liftweb.common.Box[Any] = Full(Map(foo -> 4.0)) 

Analyse JSON dans Lift 2.0 et 2.2 avec json.JsonParser

  • Recommandation neutre
  • Json.JsonParser de Lift n’parsingra pas les chaînes JSON entre guillemets simples:

Exemple:

 scala> import net.liftweb.json._ import net.liftweb.json._ scala> import net.liftweb.json.JsonParser._ import net.liftweb.json.JsonParser._ scala> parse("{\"foo\" : 4 }") res1: net.liftweb.json.JsonAST.JValue = JObject(List(JField(foo,JInt(4)))) scala> parse("[ 1,2,3 ]") res2: net.liftweb.json.JsonAST.JValue = JArray(List(JInt(1), JInt(2), JInt(3))) scala> parse("{'foo' : 4}") net.liftweb.json.JsonParser$ParseException: unknown token ' Near: {'foo' : 4} at net.liftweb.json.JsonParser$Parser.fail(JsonParser.scala:216) at net.liftweb.json.JsonParser$Parser.nextToken(JsonParser.scala:308) at net.liftweb.json.JsonParser$$anonfun$1.apply(JsonParser.scala:172) at net.liftweb.json.JsonParser$$anonfun$1.apply(JsonParser.scala:129) at net.liftweb.json.JsonParse... 

Produire JSON avec Lift 1.0 JsCmd

  • Not Recommended – sortie non valide pour tous les parsingurs JSON
  • Notez les guillemets simples autour des chaînes:

Exemple:

 scala> import net.liftweb.http.js._ import net.liftweb.http.js._ scala> import net.liftweb.http.js.JE._ import net.liftweb.http.js.JE._ scala> JsObj(("foo", 4), ("bar", "baz")).toJsCmd res0: Ssortingng = {'foo': 4, 'bar': 'baz'} scala> JsArray(1,2,3).toJsCmd res1: Ssortingng = [1, 2, 3] scala> JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd res2: Ssortingng = {'foo': 4, 'bar': [1, 2, 3] } 

Produire JSON avec Lift 2.0 JsCmd

  • Recommandation neutre
  • Notez les doubles citations autour des chaînes:

Exemple:

 scala> import net.liftweb.http.js._ import net.liftweb.http.js._ scala> import net.liftweb.http.js.JE._ import net.liftweb.http.js.JE._ scala> JsObj(("foo", 4), ("bar", "baz")).toJsCmd res0: Ssortingng = {"foo": 4, "bar": "baz"} scala> JsArray(1,2,3).toJsCmd res1: Ssortingng = [1, 2, 3] scala> JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd res3: Ssortingng = {"foo": 4, "bar": [1, 2, 3] } 

Producint JSON dans Scala (testé avec 2.10)

  • ” Plus vraiment pris en charge “, mais ça marche et c’est là.

Exemple:

 scala> import scala.util.parsing.json._ import scala.util.parsing.json._ scala> JSONObject (Map ("foo" -> 4, "bar" -> JSONArray (1 :: 2 :: 3 :: Nil))) .toSsortingng() res0: Ssortingng = {"foo" : 4, "bar" : [1, 2, 3]} 

Jetez un oeil à Circé . C’est vraiment agréable à utiliser et il tire parti de certains des nouveaux outils de Shapeless et Cats . De plus, vous pouvez l’utiliser à partir de Scala compilé en Javascript .

Extrait du readme de Circé :

scala> import io.circe. , io.circe.generic.auto. , io.circe.parser. , io.circe.syntax. import io.circe._ import io.circe.generic.auto._ import io.circe.parser._ import io.circe.syntax._

scala> trait scellé Foo défini trait Foo

scala> case class Bar (xs: List [Ssortingng]) étend la classe définie par Foo Bar

scala> classe de cas Qux (i: Int, d: option [Double]) étend la classe définie par Quoo Qux

scala> val foo: Foo = Qux (13, Quelques (14.0)) foo: Foo = Qux (13, Some (14.0))

scala> foo.asJson.noSpaces res0: Ssortingng = {“Qux”: {“d”: 14.0, “i”: 13}}

scala> decodeFoo res1: cats.data.Xor [io.circe.Error, Foo] = Droit (Qux (13, Some (14.0)))