Как сопоставить шаблон с JsArray из JsStrings - PullRequest
1 голос
/ 28 июня 2019

Например, у меня есть простой авторский JSON:

{
  "name": "string",
  "articles": [
    "string",
    "string",
    "string"
  ]
}

Я определяю формат чтения Json:

implicit object authorFormat extends RootJsonFormat[Author] {
  override def write(a: Author) = ???

  override def read(json: JsValue) = json.asJsObject.getFields("name", "articles") match {
    case Seq(JsString(name), JsArray(articles)) => ... //Build author
  }
}

Это сопоставление с шаблоном гарантирует "articles" массив (JsValues). Но это не гарантирует, "articles" это массив строк. Как это исправить?

1 Ответ

1 голос
/ 28 июня 2019

Попробуйте десериализацию от articles до List[String], как, например,

articles.map(_.convertTo[String]).toList

, если jsonFormat2 не вариант. Вот рабочий пример

import spray.json._
import DefaultJsonProtocol._

object MyApp extends App {
  case class Author(name: String, articles: List[String])

  implicit object authorFormat extends RootJsonFormat[Author] {
    override def write(a: Author) = ???

    override def read(json: JsValue) = json.asJsObject.getFields("name", "articles") match {
      case Seq(JsString(name), JsArray(articles)) => Author(name, articles.map(_.convertTo[String]).toList)
    }
  }

  val raw =
    """
      |{
      |  "name": "string",
      |  "articles": [
      |    "string,
      |    "string",
      |    "string"
      |  ]
      |}
    """.stripMargin



  val json = raw.parseJson
  val author = json.convertTo[Author]
  println(author)
}

который выводит

Author(string,List(string, string, string))

, если articles содержит нестроковую строку, такую ​​как

  val raw =
    """
      |{
      |  "name": "string",
      |  "articles": [
      |    1,
      |    "string",
      |    "string"
      |  ]
      |}
    """.stripMargin

мы получаем ошибку

Exception in thread "main" spray.json.DeserializationException: Expected String as JsString, but got 1
...