如何在 Scala 中解析 JSON 数据?
How to parse JSON data in Scala?
我是 Scala 新手。我想在 scala 中解析 JSON 数据。
我想循环此数据并在每次迭代中从值
中提取 id,v,q
和 t
的数据
我正在使用下面的代码将其解析为 JSON
import scala.util.parsing.json._
val data =
"""
{
"timestamp":
1518501114949
, "values":
[
{
"id":
"abc"
, "v":
0
, "q":
true
, "t":
1518501114487
}
,
{
"id":
"xyz"
, "v":
15
, "q":
true
, "t":
1518501114494
}
]
}
"""
val parsed = JSON.parseFull(data)
我得到如下输出
Some(Map(timestamp -> 1.518501114949E12, values -> List(Map(id -> abc, v -> 0.0, q -> true, t -> 1.518501114487E12), Map(id -> xyz, v -> 15.0, q -> true, t -> 1.518501114494E12), Map(id -> klm, v -> 12.6999998, q -> true, t -> 1.518501114487E12), Map(id -> 901.Hotmelt.PSA.0759_PSAM01_Vac, v -> 1.0, q -> true, t -> 1.518501114494E12))))
但我不知道如何循环并获取之后的所有值
而且我不明白为什么时间戳会转换为 E12 值
问题是 parseFull returns 一个里面有 Any 的 Option,所以你首先需要去掉它:
使用下面的代码,您将保留以下值:
val listAsAny = parsed match {
case Some(e:Map[Any,Any]) => e("values")
case None => println("Failed.")
}
但是他们还是Any,所以你可以这样改造:
val values = listAsAny.asInstanceOf[List[Map[String, Any]]]
现在 values 是具有以下值的映射列表,您可以像处理常规列表一样获取其中的值
List(Map(id -> abc, v -> 0.0, q -> true, t -> 1.518501114487E12), Map(id -> xyz, v -> 15.0, q -> true, t -> 1.518501114494E12))
例如,要检索您可以执行的 ID:
values.map(_("id"))
结果将是:
List(abc, xyz)
关于你的第二个问题
and I am not understanding why timestamp is getting converted to E12 values
这个特殊的 JSON 解析器将所有数字都视为 Double
分数,因此这就是为什么您会得到带分数 × 10^2(E12
后缀)的科学记数法。关于如何更改此解析器对数字的默认行为有一个答案 here,即可以实现自己的解析器 return Long
而不是默认的 Double
.
如果你有大整数时间戳要解析更有意义,因为你很容易开始失去精度(如果超过 2^51 ~= 4,5×10¹⁵,时间戳将被四舍五入,这是 [=10 的边界=] 输入小数部分精度)。但是,在您的情况下,像 1518501114949 这样的数字要小 100 倍,因此仍然有一些安全余量,并且可能使用 .toLong
方法将结果 Double
转换为 Long
就足够了。
upickle 库提供了一个强大、优雅的解决方案。
val parsed = ujson.read(data)
parsed("values").arr.map(_("id").str) // ArrayBuffer("abc", "xyz")
有关为什么 upickle / ujson 是用于解析的最佳 Scala 库的更详细讨论,请参阅 here JSON。
我是 Scala 新手。我想在 scala 中解析 JSON 数据。
我想循环此数据并在每次迭代中从值
中提取id,v,q
和 t
的数据
我正在使用下面的代码将其解析为 JSON
import scala.util.parsing.json._
val data =
"""
{
"timestamp":
1518501114949
, "values":
[
{
"id":
"abc"
, "v":
0
, "q":
true
, "t":
1518501114487
}
,
{
"id":
"xyz"
, "v":
15
, "q":
true
, "t":
1518501114494
}
]
}
"""
val parsed = JSON.parseFull(data)
我得到如下输出
Some(Map(timestamp -> 1.518501114949E12, values -> List(Map(id -> abc, v -> 0.0, q -> true, t -> 1.518501114487E12), Map(id -> xyz, v -> 15.0, q -> true, t -> 1.518501114494E12), Map(id -> klm, v -> 12.6999998, q -> true, t -> 1.518501114487E12), Map(id -> 901.Hotmelt.PSA.0759_PSAM01_Vac, v -> 1.0, q -> true, t -> 1.518501114494E12))))
但我不知道如何循环并获取之后的所有值
而且我不明白为什么时间戳会转换为 E12 值
问题是 parseFull returns 一个里面有 Any 的 Option,所以你首先需要去掉它:
使用下面的代码,您将保留以下值:
val listAsAny = parsed match {
case Some(e:Map[Any,Any]) => e("values")
case None => println("Failed.")
}
但是他们还是Any,所以你可以这样改造:
val values = listAsAny.asInstanceOf[List[Map[String, Any]]]
现在 values 是具有以下值的映射列表,您可以像处理常规列表一样获取其中的值
List(Map(id -> abc, v -> 0.0, q -> true, t -> 1.518501114487E12), Map(id -> xyz, v -> 15.0, q -> true, t -> 1.518501114494E12))
例如,要检索您可以执行的 ID:
values.map(_("id"))
结果将是:
List(abc, xyz)
关于你的第二个问题
and I am not understanding why timestamp is getting converted to E12 values
这个特殊的 JSON 解析器将所有数字都视为 Double
分数,因此这就是为什么您会得到带分数 × 10^2(E12
后缀)的科学记数法。关于如何更改此解析器对数字的默认行为有一个答案 here,即可以实现自己的解析器 return Long
而不是默认的 Double
.
如果你有大整数时间戳要解析更有意义,因为你很容易开始失去精度(如果超过 2^51 ~= 4,5×10¹⁵,时间戳将被四舍五入,这是 [=10 的边界=] 输入小数部分精度)。但是,在您的情况下,像 1518501114949 这样的数字要小 100 倍,因此仍然有一些安全余量,并且可能使用 .toLong
方法将结果 Double
转换为 Long
就足够了。
upickle 库提供了一个强大、优雅的解决方案。
val parsed = ujson.read(data)
parsed("values").arr.map(_("id").str) // ArrayBuffer("abc", "xyz")
有关为什么 upickle / ujson 是用于解析的最佳 Scala 库的更详细讨论,请参阅 here JSON。