如何在没有大小写的情况下解析 JSON Scala 类
How to parse a JSON Scala without case classes
我有一个 JSON 可以随时间改变,使用 case Class 可能不方便,因为每次 JSON 改变时我都需要改变它的结构。
例如,如果我有这样的 JSON:
val json= """{
"accounts": [
{ "emailAccount": {
"accountName": "YMail",
"username": "USERNAME",
"password": "PASSWORD",
"url": "imap.yahoo.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["barney", "betty", "wilma"]
}},
{ "emailAccount": {
"accountName": "Gmail",
"username": "USER",
"password": "PASS",
"url": "imap.gmail.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["pebbles", "bam-bam"]
}}
]
}"""
我可以通过类似的方式访问它吗:
val parsedJSON = parse(json)
parsedJSON.accounts(0).emailAccount.accountName
circe 的光学模块几乎完全支持您要求的语法:
import io.circe.optics.JsonPath.root
val accountName = root.accounts.at(0).emailAccount.accountName.as[String]
然后如果你有这个 JSON 值(我正在使用 circe 的 JSON 文字支持,但你也可以用 io.circe.jawn.parse
解析字符串(parse 函数)来获得你正在使用的 Json
值):
import io.circe.Json, io.circe.literal._
val json: Json = json"""{
"accounts": [
{ "emailAccount": {
"accountName": "YMail",
"username": "USERNAME",
"password": "PASSWORD",
"url": "imap.yahoo.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["barney", "betty", "wilma"]
}},
{ "emailAccount": {
"accountName": "Gmail",
"username": "USER",
"password": "PASS",
"url": "imap.gmail.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["pebbles", "bam-bam"]
}}
]
}"""
您可以尝试像这样访问帐户名:
scala> accountName.getOption(json)
res0: Option[String] = Some(YMail)
因为 circe-optics 是建立在 Monocle 之上的,所以您可以获得一些其他不错的功能,例如不可变更新:
scala> accountName.modify(_.toLowerCase)(json)
res2: io.circe.Json =
{
"accounts" : [
{
"emailAccount" : {
"accountName" : "ymail",
...
以此类推
更新:circe 被设计成模块化的,因此您只 "pay for" 您需要的部分。上面的示例期望 SBT 的设置类似于以下设置:
scalaVersion := "2.11.8"
val circeVersion = "0.4.1"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % circeVersion,
"io.circe" %% "circe-jawn" % circeVersion,
"io.circe" %% "circe-literal" % circeVersion,
"io.circe" %% "circe-optics" % circeVersion
)
…或者对于 Maven:
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-core_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-jawn_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-literal_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-optics_2.11</artifactId>
<version>0.4.1</version>
</dependency>
我有一个 JSON 可以随时间改变,使用 case Class 可能不方便,因为每次 JSON 改变时我都需要改变它的结构。
例如,如果我有这样的 JSON:
val json= """{
"accounts": [
{ "emailAccount": {
"accountName": "YMail",
"username": "USERNAME",
"password": "PASSWORD",
"url": "imap.yahoo.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["barney", "betty", "wilma"]
}},
{ "emailAccount": {
"accountName": "Gmail",
"username": "USER",
"password": "PASS",
"url": "imap.gmail.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["pebbles", "bam-bam"]
}}
]
}"""
我可以通过类似的方式访问它吗:
val parsedJSON = parse(json)
parsedJSON.accounts(0).emailAccount.accountName
circe 的光学模块几乎完全支持您要求的语法:
import io.circe.optics.JsonPath.root
val accountName = root.accounts.at(0).emailAccount.accountName.as[String]
然后如果你有这个 JSON 值(我正在使用 circe 的 JSON 文字支持,但你也可以用 io.circe.jawn.parse
解析字符串(parse 函数)来获得你正在使用的 Json
值):
import io.circe.Json, io.circe.literal._
val json: Json = json"""{
"accounts": [
{ "emailAccount": {
"accountName": "YMail",
"username": "USERNAME",
"password": "PASSWORD",
"url": "imap.yahoo.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["barney", "betty", "wilma"]
}},
{ "emailAccount": {
"accountName": "Gmail",
"username": "USER",
"password": "PASS",
"url": "imap.gmail.com",
"minutesBetweenChecks": 1,
"usersOfInterest": ["pebbles", "bam-bam"]
}}
]
}"""
您可以尝试像这样访问帐户名:
scala> accountName.getOption(json)
res0: Option[String] = Some(YMail)
因为 circe-optics 是建立在 Monocle 之上的,所以您可以获得一些其他不错的功能,例如不可变更新:
scala> accountName.modify(_.toLowerCase)(json)
res2: io.circe.Json =
{
"accounts" : [
{
"emailAccount" : {
"accountName" : "ymail",
...
以此类推
更新:circe 被设计成模块化的,因此您只 "pay for" 您需要的部分。上面的示例期望 SBT 的设置类似于以下设置:
scalaVersion := "2.11.8"
val circeVersion = "0.4.1"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % circeVersion,
"io.circe" %% "circe-jawn" % circeVersion,
"io.circe" %% "circe-literal" % circeVersion,
"io.circe" %% "circe-optics" % circeVersion
)
…或者对于 Maven:
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-core_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-jawn_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-literal_2.11</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>io.circe</groupId>
<artifactId>circe-optics_2.11</artifactId>
<version>0.4.1</version>
</dependency>