如何在 Scala/Lift 中构造和解析 JSON 字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/927983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I construct and parse a JSON string in Scala / Lift
提问by David Carlson
I am attempting to use JSON to send data between the browser and my app.
我正在尝试使用 JSON 在浏览器和我的应用程序之间发送数据。
I am attempting to use Lift 1.0 to create and parse JSON strings, but for some reason I am unable to parse the JSON I just constructed:
我正在尝试使用 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
How do I programmatically construct a valid JSON message in Scala/Lift that can also be parsed again?
如何在 Scala/Lift 中以编程方式构造一个有效的 JSON 消息,该消息也可以再次解析?
回答by David Carlson
You are using Lift 1.0's JsCmd, which produces JSON with single-quoted strings and attempting to parse it with scala's parser, which only supports double-quoted strings.
您正在使用 Lift 1.0's JsCmd,它生成带有单引号字符串的 JSON 并尝试使用仅支持双引号字符串的 scala 解析器解析它。
It is important to realize that there are multiple definitions for JSON.
重要的是要意识到 JSON 有多种定义。
Are single-quoted strings valid in JSON?
单引号字符串在 JSON 中有效吗?
- They are according to ECMAScript 5th Ed
- They are not according to Crockford's original RFC 4627
- 它们是根据ECMAScript 5th Ed
- 它们不符合 Crockford 的原始RFC 4627
Lift and Scala provide many ways to parse JSON, sometimes with differing behavior between versions.
Lift 和 Scala 提供了许多解析 JSON 的方法,有时版本之间的行为不同。
The strings accepted by these parsers are not equivalent.
这些解析器接受的字符串是不等价的。
Here are some comments and examples of the various methods to product and parse JSON strings.
以下是生成和解析 JSON 字符串的各种方法的一些注释和示例。
Producing JSON with the lift-jsonlibrary DSL
使用 Lift -json库 DSL生成 JSON
- Recommended
- Despite its name, this is a separate project with no dependencies on the rest of Lift
- 受到推崇的
- 尽管它的名字,这是一个独立的项目,不依赖于 Lift 的其余部分
example:
例子:
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]}
Parsing JSON with the lift-jsonlibrary
使用lift-json库解析 JSON
- Recommended
- Provides implicit mapping to/from scala case-classes
- Case-classes defined in the console are not currently supported (will throw a
com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes) - The example below uses
PublicID, a pre-existing scala case-class so that it will work on the scala console.
- 受到推崇的
- 提供到/从 Scala 案例类的隐式映射
- 当前不支持在控制台中定义的案例类(将抛出
com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytes) - 下面的示例使用
PublicID,一个预先存在的 scala 案例类,以便它可以在 scala 控制台上工作。
example:
例子:
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"
Parsing JSON in scala 2.7.7 and 2.8.1
在 Scala 2.7.7 和 2.8.1 中解析 JSON
- Not Recommended - "No longer really supported"
- Scala 2.7.7's parser will not parse single-quoted JSON
- This parsing method used in the question
- 不推荐 - “不再真正支持”
- Scala 2.7.7 的解析器不会解析单引号 JSON
- 问题中使用的这种解析方法
example:
例子:
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
Parsing JSON in Lift 2.0 and 2.2 with util.JSONParser
使用util.JSONParser在 Lift 2.0 和 2.2 中解析 JSON
- Neutral Recommendation
- Lift's util.JSONParser will parse single- or double-quoted JSON strings:
- 中立推荐
- Lift 的 util.JSONParser 将解析单引号或双引号 JSON 字符串:
example:
例子:
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))
Parsing JSON in Lift 2.0 and 2.2 with json.JsonParser
使用json.JsonParser在 Lift 2.0 和 2.2 中解析 JSON
- Neutral Recommendation
- Lift's json.JsonParser will not parse single-quoted JSON strings:
- 中立推荐
- Lift 的 json.JsonParser 不会解析单引号 JSON 字符串:
example:
例子:
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...
Producing JSON with Lift 1.0 JsCmd
使用 Lift 1.0 JsCmd 生成 JSON
- Not Recommended - output not valid for all JSON parsers
- Note the single-quotations around strings:
- 不推荐 - 输出不适用于所有 JSON 解析器
- 注意字符串周围的单引号:
example:
例子:
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]
}
Producing JSON with Lift 2.0 JsCmd
使用 Lift 2.0 JsCmd 生成 JSON
- Neutral Recommendation
- Note the double quotations around strings:
- 中立推荐
- 注意字符串周围的双引号:
example:
例子:
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]
}
Producing JSON in scala (tested with 2.10)
在 Scala 中生成 JSON(使用 2.10 测试)
- "No longer really supported", but it works and it's there.
- “不再真正受支持”,但它可以工作并且就在那里。
example:
例子:
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]}
回答by James Moore
Take a look at Circe. It's really nice to use and it leverages some of the new tools from Shapelessand Cats. Plus, you can use it from Scala compiled to Javascript.
看看Circe。它使用起来非常好,它利用了Shapeless和Cats 的一些新工具。另外,您可以从编译为 Javascript 的 Scala使用它。
Taken from the Circe readme:
取自Circe 自述文件:
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> sealed trait Foo defined trait Foo
scala> case class Bar(xs: List[String]) extends Foo defined class Bar
scala> case class Qux(i: Int, d: Option[Double]) extends Foo defined class Qux
scala> val foo: Foo = Qux(13, Some(14.0)) foo: Foo = Qux(13,Some(14.0))
scala> foo.asJson.noSpaces res0: String = {"Qux":{"d":14.0,"i":13}}
scala> decodeFoo res1: cats.data.Xor[io.circe.Error,Foo] = Right(Qux(13,Some(14.0)))
Scala> 导入 io.circe。, io.circe.generic.auto。, io.circe.parser。, io.circe.syntax。导入 io.circe._ 导入 io.circe.generic.auto._ 导入 io.circe.parser._ 导入 io.circe.syntax._
scala> 密封 trait Foo 定义的 trait Foo
scala> case class Bar(xs: List[String]) 扩展 Foo 定义的类 Bar
scala> case class Qux(i: Int, d: Option[Double]) 扩展 Foo 定义的类 Qux
Scala> val foo: Foo = Qux(13, Some(14.0)) foo: Foo = Qux(13,Some(14.0))
Scala> foo.asJson.noSpaces res0: String = {"Qux":{"d":14.0,"i":13}}
Scala> decodeFoo res1:cats.data.Xor[io.circe.Error,Foo] = Right(Qux(13,Some(14.0)))

