Разбирать пустую строку как None с помощью Json4s

#scala #serialization #optional #json4s

#scala #сериализация #тип параметра #json4s

Вопрос:

Я знаю, что Json4s обрабатывает Option s самостоятельно, и большую часть времени это отлично работает — Option[T] он сериализует None пропущенное значение и считывает пропущенное значение как None , автоматически используя правильный сериализатор / десериализатор для T в противном случае.

Моя проблема в том, что у меня есть база данных, в которой пустые строки использовались как отсутствующие значения, поэтому я хочу прочитать их как None . Простой пример:

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

Я думал, что смогу сделать это довольно легко с помощью пользовательского сериализатора, например:

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

Это работает для чтения пустых строк как None , однако, если значение JSON не является пустой строкой, это приведет к ошибкам (т. Е. в предыдущем примере это выдало бы ошибку {"a": "5"} ).). Как я могу заставить Json4s продолжить разбор значения, используя его поведение по умолчанию, если это не пустая строка?

Теоретически я думал об использовании typetag T и добавлении регистра по умолчанию, подобного case v => Serialization.write[T](v) , но я не уверен, что это лучший способ, и я также не могу понять, как это будет выглядеть в коде.

Комментарии:

1. Хотя я не использовал Json4s, но я вижу, что вы просто ловите "" by case JString("") => None в своей пользовательской сериализации. Как насчет другого? Я думаю, вам также нужны case x@_:JsString => ??? и другие типы перехвата.

2. @MHJ я знаю, как перехватывать другие значения ( case _ => ??? ) проблема в том, что я не знаю, есть ли какой-то способ заставить Json4s продолжать попытки с другими сериализаторами.

3. Есть ли причина, по которой вам нужно использовать Json4s конкретно? Это действительно довольно ужасная библиотека по сравнению, например, с circe.

4. @MatthiasBerndt Это то, что используется — у меня нет возможности изменить это.

Ответ №1:

Немного поздновато для прохождения, но вам просто нужно еще одно заявление по делу

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