Pregunta

Estoy intentando utilizar JSON para enviar datos entre el navegador y mi aplicación.

Estoy intentando utilizar Lift 1.0 para crear y analizar cadenas JSON, pero por alguna razón no puedo analizar el JSON que acabo de construir:

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: String = {'foo': 4, 'bar': 'baz'}

scala>  parseFull(json)  
res3: Option[Any] = None

¿Cómo construyo mediante programación un mensaje JSON válido en Scala/Lift que también se puede analizar nuevamente?

¿Fue útil?

Solución

Estás usando Lift 1.0 JsCmd, que produce JSON con cadenas entre comillas simples e intenta analizarlo con el analizador de Scala, que solo admite cadenas entre comillas dobles.

Es importante darse cuenta de que existen múltiples definiciones para JSON.

¿Son válidas las cadenas entre comillas simples en JSON?

Lift y Scala proporcionan muchas formas de analizar JSON, a veces con comportamientos diferentes entre versiones.

Las cadenas aceptadas por estos analizadores no son equivalentes.

A continuación se muestran algunos comentarios y ejemplos de los distintos métodos para producir y analizar cadenas JSON.


Producir JSON con el levantar-json biblioteca DSL

  • Recomendado
  • A pesar de su nombre, se trata de un proyecto independiente que no depende del resto de Lift.

ejemplo:

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,JString(baz))))

scala> compact(JsonAST.render(json1))
res0: String = {"foo":4,"bar":"baz"}

scala> val json2 = List(1,2,3)
json2: List[Int] = List(1, 2, 3)

scala> compact(JsonAST.render(json2))
res1: String = [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: String = {"foo":4,"bar":[1,2,3]}

Analizando JSON con el levantar-json biblioteca

  • Recomendado
  • Proporciona mapeo implícito hacia/desde clases de casos de Scala
  • Las clases de casos definidas en la consola no son compatibles actualmente (arrojará un com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes)
  • El siguiente ejemplo utiliza ID pública, una clase de caso de Scala preexistente para que funcione en la consola de Scala.

ejemplo:

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" -> "idString") ~ ("systemId" -> "systemIdStr")
jsonAst: net.liftweb.json.JsonAST.JObject = JObject(List(JField(publicId,JString(idString)), JField(systemId,JString(systemIdStr))))

scala> jsonAst.extract[PublicID]
res0: scala.xml.dtd.PublicID = PUBLIC "idString" "systemIdStr"

Análisis de JSON en Scala 2.7.7 y 2.8.1

  • No recomendado - "Ya no es realmente compatible"
  • El analizador de Scala 2.7.7 no analizará JSON entre comillas simples
  • Este método de análisis utilizado en la pregunta.

ejemplo:

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

Analizando JSON en Lift 2.0 y 2.2 con util.JSONParser

  • Recomendación neutral
  • util.JSONParser de Lift analizará cadenas JSON entre comillas simples o dobles:

ejemplo:

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

Analizando JSON en Lift 2.0 y 2.2 con json.JsonParser

  • Recomendación neutral
  • Json.JsonParser de Lift no analizará cadenas JSON entre comillas simples:

ejemplo:

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...

Produciendo JSON con Lift 1.0 JsCmd

  • No recomendado: la salida no es válida para todos los analizadores JSON
  • Tenga en cuenta las comillas simples alrededor de las cadenas:

ejemplo:

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: String = {'foo': 4, 'bar': 'baz'}

scala> JsArray(1,2,3).toJsCmd
res1: String = 
[1, 2, 3]

scala>  JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd
res2: String = 
{'foo': 4, 'bar': [1, 2, 3]
}

Produciendo JSON con Lift 2.0 JsCmd

  • Recomendación neutral
  • Tenga en cuenta las comillas dobles alrededor de las cadenas:

ejemplo:

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: String = {"foo": 4, "bar": "baz"}

scala> JsArray(1,2,3).toJsCmd
res1: String = 
[1, 2, 3]

scala> JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd
res3: String = 
{"foo": 4, "bar": [1, 2, 3]
}

Produciendo JSON en Scala (probado con 2.10)

ejemplo:

scala> import scala.util.parsing.json._
import scala.util.parsing.json._

scala> JSONObject (Map ("foo" -> 4, "bar" -> JSONArray (1 :: 2 :: 3 :: Nil))) .toString()
res0: String = {"foo" : 4, "bar" : [1, 2, 3]}

Otros consejos

Tome un vistazo a Circe . Es muy agradable de usar y aprovecha algunas de las nuevas herramientas de Sin forma y Gatos . Además, se puede usar desde Scala compilado a Javascript.

Circe readme :

  

Scala> io.circe importación. , io.circe.generic.auto. , io.circe.parser. ,   io.circe.syntax. io.circe._ importación io.circe.generic.auto._ importación   importar importar io.circe.parser._ io.circe.syntax ._

     

Scala> rasgo sellado Foo rasgo definido Foo

     

Scala> caso Bar clase (xs: Lista [String]) se extiende Foo clase definida Bar

     

Scala> Clase caso Qux (i: Int, d: Opción [Doble]) se extiende Foo definido   clase Qux

     

Scala> val foo: Foo = Qux (13, algunos (14.0)) foo: Foo =   Qux (13, algunos (14.0))

     

Scala> foo.asJson.noSpaces res0: String = { "Qux": { "d": 14,0, "i": 13}}

     

Scala> decodeFoo res1:   cats.data.Xor [io.circe.Error, Foo] = Derecho (Qux (13, algunos (14.0)))

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top