Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to read json with an optional field serialized by a missing field, in upickle

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
like image 552
David Portabella Avatar asked Nov 04 '19 13:11

David Portabella


1 Answers

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
)
like image 67
moneretin Avatar answered Nov 03 '22 15:11

moneretin