Как я могу построить и проанализировать строку JSON в Scala / Lift


Я пытаюсь использовать JSON для отправки данных между браузером и моим приложением.

Я пытаюсь использовать Lift 1.0 для создания и анализа строк JSON, но по какой-то причине я не могу разобрать JSON, который я только что построил:

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

как программно построить допустимое сообщение JSON в Scala / Lift, которое также может быть проанализировано снова?

2 52

2 ответа:

вы используете лифт 1.0 л!--8-->, который создает JSON с строками в одинарных кавычках и пытается проанализировать его с помощью синтаксического анализатора scala, который поддерживает только строки в двойных кавычках.

важно понимать, что существует несколько определений для JSON.

допустимы ли строки в одинарных кавычках в JSON?

  • они согласно ECMAScript 5th Ed
  • они не соответствуют оригиналу Крокфорда RFC 4627

Lift и Scala предоставляют множество способов анализа JSON, иногда с различным поведением между версиями.

строки, принятые этими синтаксическими анализаторами, не эквивалентны.

вот некоторые комментарии и примеры различных методов для продукта и разбора строк JSON.


производство JSON с лифт-JSON-формате библиотека DSL

  • рекомендовано
  • несмотря на свое название, это отдельный проект без каких-либо зависимостей от остальной части Lift

пример:

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]}

разбор JSON с помощью лифт-JSON-формате библиотека

  • рекомендовано
  • обеспечивает неявное отображение в / из Scala case-classes
  • Case-классы, определенные в консоли, в настоящее время не поддерживаются (бросит com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes)
  • в приведенном ниже примере используется PublicID, уже существующий класс Scala case, чтобы он работал на консоли scala.

пример:

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"

разбор JSON в scala 2.7.7 и 2.8.1

  • Не Рекомендуется - "больше не поддерживается"
  • парсер Scala 2.7.7 не будет анализировать одинарные кавычки JSON
  • этот метод анализа используется в вопрос

пример:

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

разбор JSON в лифте 2.0 и 2.2 с util.JSONParser

  • Нейтральная Рекомендация
  • лифт в утиль.JSONParser будет анализировать строки JSON в одинарных или двойных кавычках:

пример:

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

разбор JSON в лифте 2.0 и 2.2 с в формате JSON.JsonParser

  • нейтральный Рекомендация
  • лифт json.JsonParser не будет анализировать строки JSON в одинарных кавычках:

пример:

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.apply(JsonParser.scala:172)
    at net.liftweb.json.JsonParser$$anonfun.apply(JsonParser.scala:129)
    at net.liftweb.json.JsonParse...

производить JSON с подъемом 1.0 JsCmd

  • не рекомендуется-вывод недопустим для всех парсеров 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> 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]
}

производить JSON с подъемом 2.0 JsCmd

  • Нейтральная Рекомендация
  • обратите внимание на двойные кавычки вокруг строки:

пример:

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]
}

Producint JSON в scala (тестируется с 2.10)

пример:

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]}

посмотри Цирцея. Это действительно приятно использовать и он использует некоторые из новых инструментов из бесформенные и кошки. Кроме того, вы можете использовать его из Scala скомпилирован на Javascript.

взято с Circe readme:

scala > импорт ввода-вывода.Цирцея., io.Цирцея.родовой.автоматический., io.Цирцея.синтаксический анализатор., Ио.Цирцея.синтаксис. импорт ввода-вывода.Цирцея._ импорт Ио.Цирцея.родовой.автоматический._ импорт Ио.Цирцея.синтаксический анализатор._ import io.Цирцея.синтаксис._

scala > запечатанный признак Foo определенный признак Foo

scala > case class Bar (xs: List[String]) расширяет Foo определенный класс Bar

scala > case class Qux (i: Int, d: Option[Double]) расширяет Foo defined Qux класс

scala > val foo: Foo = Qux (13, Некоторые(14.0)) foo: Foo = Qux(13,Некоторые(14.0))

scala> foo.asJson.noSpaces res0: String = {"Qux": {"d": 14.0,"i": 13}}

scala> decodeFoo res1: кошки.данные.Гаммирования[Ио.Цирцея.Error, Foo] = Right(Qux(13,Some (14.0)))