0

I know Json4s handles Options on its own and most of the time this works great - for Option[T] it serializes None to missing value and reads missing value as None while automatically using the correct serializer/deserializer for T otherwise.

My problem is that I have a database where empty strings have been used as missing values, so I want to read those as None. A simple example:

case class Example(a: Option[Number])
val inputJson = """ {"a": ""} """
Serialization.read[Example](inputJson) // I want Example(None)

I thought I could do this pretty easily with a custom serializer, for example:

case object EmptyValueSerializer extends CustomSerializer[Option[_]](_ => (
  {case JString("") => None},
  {PartialFunction.empty}
))

This does work to read empty strings as None, however if the JSON value is not an empty string, it errors (ie, for the previous example, it would throw an error on {"a": "5"}). How can I get Json4s to continue parsing the value using it's default behavior if it's not an empty string?

Theoretically I thought about using a typetag T and adding a default case like case v => Serialization.write[T](v), but I'm not sure if that's the best way and I also can't really wrap my head around what that would look like in code.

Ian
  • 5,704
  • 6
  • 40
  • 72
  • Though I have not used Json4s, but I am seeing you are just catching `""` by `case JString("") => None` in your custom Serialization. What about other ? I think you also need `case x@_:JsString => ???` and other types catching. – John Aug 25 '20 at 17:21
  • @MHJ I know how to catch other values (`case _ => ???`) the problem is I don't know if there's some way to get Json4s to keep trying with other serializers. – Ian Aug 25 '20 at 17:31
  • Any reason why you need to use Json4s specifically? It's really a pretty awful library compared to e. g. circe. – Matthias Berndt Aug 25 '20 at 18:15
  • @MatthiasBerndt That's what's in use - I don't have the power to change it. – Ian Aug 28 '20 at 13:23

1 Answers1

0

A bit late to the pass but you just need another case statement

case object EmptyValueSerializer extends CustomSerializer[Option[_]](_ => (
  {
    case JString("") => None
    case JString(s) => Option(s)
  },
  {PartialFunction.empty}
))
gaf
  • 191
  • 1
  • 1
  • 8