Подтвердить что ты не робот

Можно ли заставить json4s не генерировать исключение, если отсутствует требуемое поле?

Можно ли заставить json4s не генерировать исключение, если требуемое поле отсутствует?

Когда я "извлекаю" объект из строки raw json, он выдает исключение, подобное этому

org.json4s.package$MappingException: No usable value for pager
No usable value for rpp
Did not find value which can be converted into byte
    at org.json4s.reflect.package$.fail(package.scala:98)
    at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:388)
    at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$11.apply(Extraction.scala:396)

Возможно ли это, чтобы оно было пустым?

4b9b3361

Ответ 1

Это довольно просто, вы должны использовать Option и его потенциалы, Some и None.

val json = ("name" -> "joe") ~ ("age" -> Some(35));
val json = ("name" -> "joe") ~ ("age" -> (None: Option[Int]))

Обратите внимание, что в приведенном выше случае Option будет выполняться match. Если он None, он будет полностью удален из строки, поэтому он не будет возвращать нулевое значение.

В том же шаблоне, чтобы проанализировать неполный JSON, вы используете case class с Option.

case class someModel(
    age: Option[Int],
    name: Option[String]
);
val json = ("name" -> "joe") ~ ("age" -> None);
parse(json).extract[someModel];

Существует метод, который не будет вызывать никаких исключений, а это extractOpt

parse(json).extractOpt[someModel];

Способом репликации этого с помощью API scala будет использование scala.util.Try:

Try { parse(json).extract[someModel] }.toOption

Ответ 2

Я столкнулся с этой проблемой при работе с миграциями данных, и я хотел, чтобы значения по умолчанию заполняли поля undefined.

Мое решение состояло в том, чтобы объединить значения по умолчанию в JValue, прежде чем извлекать результат.

  val defaultsJson = Extraction.decompose(defaults)
  val valueJson = JsonUtil.jValue(v)
  (defaultsJson merge valueJson).extract[T]

JsonUtil.scala

  import org.json4s._

  object JsonUtil {
    import java.nio.charset.StandardCharsets.UTF_8
    import java.io.{InputStreamReader, ByteArrayInputStream}

    def jValue(json: String): JValue = {
      jValue(json.getBytes(UTF_8))
    }

    def jValue(json: Array[Byte]): JValue = {
      val reader = new InputStreamReader(new ByteArrayInputStream(json), UTF_8)
      native.JsonParser.parse(reader)
    }
  }