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