Search code examples
scalaspray-json

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?


Solution

  • 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