Scala - как взять json в качестве входных аргументов и разобрать его? - PullRequest
0 голосов
/ 12 января 2019

Я пишу небольшой тренировочный код для 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 в моем коде?

1 Ответ

0 голосов
/ 12 января 2019

Вы можете использовать библиотеку json, например play-json , для анализа содержимого json.

Вы можете работать с json AST или писать классы дел, которые имеют ту же структуру, что и ваш файл json, и разрешать их анализировать.

Документацию библиотеки можно найти здесь .


Сначала вам нужно добавить playjson в качестве зависимости к вашему проекту. Если вы используете sbt, просто добавьте в свой файл build.sbt:

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

Воспроизвести JSON с помощью AST

Давайте прочитаем входной файл:

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]}")

Использование десериализации

Как я только что описал, мы можем создавать case-классы, которые представляют вашу структуру:

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, например. в сопутствующем объекте каждого класса case. Вместо того чтобы писать его вручную, вы можете использовать макрос 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, который облегчает доступ к полям с пробелами и аналогичным по названию:

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`
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...