Scala - 如何将 json 作为输入参数并解析它?

Scala - how to take json as input arguments and parse it?

我正在编写一个小的 scala 练习代码,我的输入将成为时尚 -

{
  "code": "",
  "unique ID": "",
  "count": "",
  "names": [
    {
      "Matt": {
        "name": "Matt",
        "properties": [
          "a",
          "b",
          "c"
        ],
        "fav-colour": "red"
      },
      "jack": {
        "name": "jack",
        "properties": [
          "a",
          "b"
        ],
        "fav-colour": "blue"
      }
    }
  ]
}

我会将此文件作为命令行参数传递。 我想知道如何接受输入文件解析 json 并在我的代码中使用 json 键?

您可以使用 json 库,例如 play-json 来解析 json 内容。

您可以对 json AST 进行操作,或者您可以编写与 json 文件具有相同结构的 case classes 并让它们被解析。

您可以找到库的文档 here


您首先必须将 playjson 作为依赖项添加到您的项目中。如果您使用的是 sbt,只需添加到您的 build.sbt 文件:

libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.13"

使用 AST

播放 json

让我们读取输入文件:

import play.api.libs.json.Json

object Main extends App {
  // first we'll need a inputstream of your json object
  // this should be familiar if you know java.
  val in = new FileInputStream(args(0))

  // now we'll let play-json parse it
  val json = Json.parse(in)
}

让我们从 AST 中提取一些字段:

val code = (json \ "code").as[String]
val uniqueID = (json \ "unique ID").as[UUID]

for {
  JsObject(nameMap) ← (json \ "names").as[Seq[JsObject]]
  (name, userMeta) ← nameMap // nameMap is a Map[String, JsValue]
} println(s"User $name has the favorite color ${(userMeta \ "fav-colour").as[String]}")

使用反序列化

正如我刚才所描述的,我们可能会创建代表您的结构的案例 classes:

case class InputFile(code: String, `unique ID`: UUID, count: String, names: Seq[Map[String, UserData]])

case class UserData(name: String, properties: Seq[String], `fav-colour`: String)

此外,您还需要定义一个隐式的 Format,例如在每个案例的伴生对象中 class。您可以使用为您导出它的 Json.format 宏,而不是手动编写它:

object UserData {
  implicit val format: OFormat[UserData] = Json.format[UserData]
}

object InputFile {
  implicit val format: OFormat[InputFile] = Json.format[InputFile]
}

您现在可以反序列化您的 json 对象:

val argumentData = json.as[InputFile]

我通常更喜欢这种方法,但在您的情况下,json 结构不太适合。一项改进可能是向您的 InputFile class 添加一个额外的 getter ,这使得访问具有 space 和类似名称的字段更容易:

case class InputFile(code: String, `unique ID`: UUID, count: String, names: Seq[Map[String, String]]) {
  // this method is nicer to use
  def uniqueId = `unique ID`
}