Reputation: 20566
I have scala class like class A(b:Seq[String])
My problem is when I deserialize it from text which have no b
field my class contains null
. It is possible to force deserealizer to fill with empty Seq
?
I use com.fasterxml.jackson.databind.ObjectMapper
with com.fasterxml.jackson.module.scala.DefaultScalaModule
.
EDIT: I want solution that fix all such fields without explicitly mentioning full list of them. Ir changing all declarations.
Upvotes: 4
Views: 1147
Reputation: 291
I had a similar problem deserializing String arrays with jackson, and found that jackson apparently (have not tried yet) fixed this in jackson-module 2.1.2. It might work for Seq. https://github.com/FasterXML/jackson-module-scala/issues/48
Upvotes: 0
Reputation: 10428
If you use Spray JSON, then a simple example which doesn't handle the absence of the b
field would look like:
import spray.json._
case class A(b: Seq[String])
object Protocol extends DefaultJsonProtocol {
implicit def aFormat = jsonFormat1(A)
}
import Protocol._
val str1 = """{ "b" : [] }""""
val str2 = """{ "b" : ["a", "b", "c"] }""""
val str3 = """{}"""
str1.parseJson.convertTo[A]//successful
str2.parseJson.convertTo[A]//successful
str3.parseJson.convertTo[A]//Deserialization error
In Spray JSON, this can be solved by writing a more detailed protocol format for class A:
import spray.json._
case class A(b: Seq[String])
object Protocol extends DefaultJsonProtocol {
implicit object aFormat extends RootJsonFormat[A] {
override def write(obj: A): JsValue = JsObject("b" -> obj.b.toJson)
override def read(json: JsValue): A = json match {
//Case where the object has exactly one member, 'b'
case JsObject(map) if map.contains("b") && map.size == 1 => A(map("b").convertTo[Seq[String]])
//Case where the object has no members
case JsObject(map) if map.isEmpty => A(Seq())
//Any other json value, which cannot be converted to an instance of A
case _ => deserializationError("Malformed")
}
}
}
import Protocol._
val str1 = """{ "b" : [] }""""
val str2 = """{ "b" : ["a", "b", "c"] }""""
val str3 = """{}"""
str1.parseJson.convertTo[A]//successful
str2.parseJson.convertTo[A]//successful
str3.parseJson.convertTo[A]//successful
Upvotes: 1
Reputation: 15464
This is not currently supported by Jackson, unfortunately.
You can see the relevant GitHub ticket here: https://github.com/FasterXML/jackson-databind/issues/347
Your best bet is to map null
into an empty Seq
in the class constructor or in an accessor method:
class A(_b: Seq[String]) {
val b = _b match {
case null => Nil
case bs => bs
}
}
(See also https://stackoverflow.com/a/20655330/8261 for other options)
Upvotes: 5