Scala unpickle with missing field

508 Views Asked by At

How can I unpickle an object with a field that might miss (and use an null) in that case?

scala> case class Person(name:String=null,age:Int)
defined class Person
scala> import scala.pickling.Defaults._, scala.pickling.json._
scala> val p2 = JSONPickle("""{"age":2}""").unpickle[Person]
scala.pickling.PicklingException: No field 'name' when unpickling, tag Person, fields were Map(age -> 2.0)

I need this in order to unpickle a string came from browser that is also missing the type field, so I will not be able to use an Option/Some/None type.

2

There are 2 best solutions below

5
On

Just declare it having type Option[String], like this:

case class Person(name: Option[String], age: Int)

Option[T] is the idiomatic Scala way of handling values which otherwise (e.g. in Java) could be null

0
On

To my understanding, scala-pickling can not handle missing fields.

If we look at the output of how scala-pickle pickles Option:

Some(9).pickle
// JSONPickle({
//   "$type": "scala.Some[scala.Int]",
//   "x": 9
// })

case class TestA(x: Option[Int])
TestA(None).pickle
// JSONPickle({
//   "$type": "TestA",
//   "x": {
//     "$type": "scala.None.type"
//   }
// })

You could use a json library instead of a serialization library.

Given your json and case class with an optional name:

case class Person(name:Option[String], age:Int)
val json =  """{"age":2}"""

With json4s:

import org.json4s._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._

parse(json).extract[Person]
// Person = Person(None,2)

With argonaut :

import argonaut._, Argonaut._

implicit def PersonCodecJson = 
  casecodec2(Person.apply, Person.unapply)("name", "age")

json.decodeOption[Person]
// Option[Person] = Some(Person(None,2))