7

I use upickle for serializing json in scalajs. I need to be able to parse optional fields, represented by a null value and by a missing field (standard json on the web).

With OptionPickler, I can accept nullable items. However, how can I accept missing fields? this example below handles the null name field, but it fails on the missing address field.

// from http://www.lihaoyi.com/upickle/ -> object OptionPickler
object OptionPickler extends upickle.AttributeTagged {
  override implicit def OptionWriter[T: Writer]: Writer[Option[T]] =
    implicitly[Writer[T]].comap[Option[T]] {
      case None => null.asInstanceOf[T]
      case Some(x) => x
    }

  override implicit def OptionReader[T: Reader]: Reader[Option[T]] = {
    new Reader.Delegate[Any, Option[T]](implicitly[Reader[T]].map(Some(_))) {
      override def visitNull(index: Int) = None
    }
  }
}

case class Person(id: Int, name: Option[String], address: Option[String])
implicit val personRW: OptionPickler.ReadWriter[Person] = OptionPickler.macroRW[Person]
val personJson = """{"id": 1, "name": null}"""
println(OptionPickler.read[Person](personJson))

Exception: upickle.core.Abort: missing keys in dictionary: address
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
David Portabella
  • 12,390
  • 27
  • 101
  • 182
  • Relatedly, why shouldn't we omit None valued Option fields by default? null and [] values imply a lot of things about data types more directly than they imply Option. Absence or Presence seems to much more deeply represent the concept of an option and cuts down payload sizes. – Ben McKenneby Jul 07 '21 at 17:28

1 Answers1

2

I solved this problem. I have case class Request. I can get schema or not from request. I process this request as follows:

import upickle.default.{ReadWriter => RW, _}

case class Request(id: Long, name: String, schema: Option[String])

implicit lazy val deserializer: Reader[Request] =
reader[ujson.Obj].map[Request](json => Request(
    read[Long](json("id")),
    read[String](json("name")),
    if (json.obj.contains("schema")) { Option(read[String](json("schema"))) } else None
)
moneretin
  • 31
  • 3