Oleg
Oleg

Reputation: 941

How to pattern match JsArray of JsStrings

For instance I have a simple author's JSON:

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

I am defining Json reading format:

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
  }
}

This pattern matching guarantees "articles" is an array(of JsValues). But it is not guarantees "articles" is an array of strings. How to fix it?

Upvotes: 2

Views: 385

Answers (1)

Mario Galic
Mario Galic

Reputation: 48430

Try deserialising articles to List[String] like so

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

if jsonFormat2 is not an option. Here is a working example

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

which outputs

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

whilst if articles contains a non-string like so

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

we get error

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

Upvotes: 1

Related Questions