У меня следующая строка:

[{"name":"Bob","age":"23"},{"name":"Alice","age":"31"},...]

И я хотел бы преобразовать его в массив:

["Bob", "Alice", ...]

Как мне этого добиться?

0
pixel 23 Окт 2018 в 15:28

2 ответа

Лучший ответ

Это довольно просто. Просто преобразуйте массив JSON в коллекцию Scala и имена карт. Например. используя Цирцею:

import io.circe._
import io.circe.generic.auto._

case class Person(name: String, age: Int)

val peopleAsJson = """[{"name":"Bob","age":"23"},{"name":"Alice","age":"31"}]"""

val personNames = decode[Vector[Person]](peopleAsJson).getOrElse(throw new Exception("Encoding failed")).map(_.name).asJson.noSpaces

Или вы можете просто сделать это через JavaScript, если это возможно.

1
Branislav Lazic 23 Окт 2018 в 12:58

Один из способов - использовать встроенный в Scala анализатор JSON. Что-то вроде этого могло бы сработать (хотя его, вероятно, можно было бы отремонтировать):

import scala.util.parsing.json._

JSON.parseFull("""[{"name":"Bob","age":"23"},{"name":"Alice","age":"31"}]""") match {
  // get the head and tail of the List and check the head's type
  case Some((m: Map[_, _]) :: l) =>
      m.keys.headOption match {
        // match type of keys - maybe unnecessary but better safe than sorry
        case Some(_: String) =>
          // add the head back to the tail, get name values
          println((m +: l).asInstanceOf[List[Map[String, Any]]]
            .map(_.getOrElse("name", "")))
        case _ => ()
      }
    case _ => ()
}

В REPL:

scala> import scala.util.parsing.json._
import scala.util.parsing.json._

scala> JSON.parseFull("""[{"name":"Bob","age":"23"},{"name":"Alice","age":"31"}]""") match {
     |   case Some((m: Map[_, _]) :: l) =>
     |       m.keys.headOption match {
     |         case Some(_: String) => println((m +: l).asInstanceOf[List[Map[String, Any]]].map(_.getOrElse("name", "")))
     |         case _ => ()
     |       }
     |     case _ => ()
     | }
List(Bob, Alice)
res0: Any = ()

Однако, если вы уже проверили структуру JSON, вы можете игнорировать всю проверку типа - этот материал просто позволяет избежать нервного расстройства, если типы не совпадают (и это более громоздко, чем идеально, из-за стирания типа).

Было бы намного проще, если бы вы использовали Scala Play и классы case (которые снова, вероятно, можно будет реорганизовать):

import play.api.libs.json.{Json, OFormat}

case class Person(name: String, age: String)
object Person {
  implicit val format: OFormat[Person] = Json.format[Person]
}

Json.parse("""[{"name":"Bob","age":"23"},{"name":"Alice","age":"31"}]""")
  .asOpt[List[Person]] match {
  case Some(people) => println(people.map(_.name)) // List(Bob, Alice)
  case _ => println(Seq())
}
0
James Whiteley 23 Окт 2018 в 12:56
52949122