json - 如何在没有案例类的情况下解析 JSON Scala

标签 json scala parsing lift-json circe

我有一个可以随时间变化的 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的 optics 模块几乎完全支持您要求的语法:

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 被设计成模块化的,因此您只需“支付”您需要的部分。上面的示例期望 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 - 如何在没有案例类的情况下解析 JSON Scala,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36724068/

相关文章:

javascript - 将json数组解析为java字符串数组

scala - 使用带有一些基类、抽象类或特征参数化列表的类型类的最佳方法

java - 从 Java 调用多态 Scala 方法

json - 使用参数 Swift 从 URL 获取数据

java - 如何更改我的正则表达式以正确匹配浮点文字?

java - 日期到字符串解析

json - 单元测试 REST API

PHP日期格式/Date(1365004652303-0500)/

java - 将无效 Json 变为有效的方法

scala - 使用 def/val/var 以及如何定义链表中的空元素