Пользовательская сериализация и десериализация scala с использованием Джексона - PullRequest
0 голосов
/ 03 марта 2020

У меня есть JSON в виде строки, которую я десериализирую и создаю в качестве экземпляра класса MyPOJO scala. Мои данные представлены в формате ГГГГ-ММ-ДД, но фактическим атрибутом в POJO createBy является LocalDateTime.

Как назначить значение времени по умолчанию 2020-03-02 00:00:00 при создании экземпляра Pojo,

Сериализация должна возвращать формат гггг-мм-дд. Мой формат сериализации и десериализации отличается.

case class MyPOJO( @JsonFormat(pattern = "yyyy-mm-dd" ) createdBy :LocalDateTime )

object MyJaxsonP {
  def main(args: Array[String]): Unit = {
    val objectMapper = new ObjectMapper() with ScalaObjectMapper
    objectMapper.findAndRegisterModules()
    objectMapper.registerModule(DefaultScalaModule)
    objectMapper.registerModule(new JavaTimeModule)
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
    val adminDatasP = objectMapper.readValue[MyPOJO]("{\"createdBy\":\"2020-03-02\"}")
    print(adminDatasP.toString)
  }
}

Я пытался с пользовательской сериализацией и десериализацией, как показано ниже, но не работает, говоря, что конструктор по умолчанию отсутствует

case class MyPOJO( @JsonDeserialize(using = classOf[CustomDateDeserializer] ) createdBy :LocalDateTime ) 

object CustomDateDeserializer {
  private val formatter = new SimpleDateFormat("dd-MM-yyyy")
}

class CustomDateDeserializer(val t: Class[String]) extends StdDeserializer[String](t) {

  override def deserialize(p: JsonParser, ctxt: DeserializationContext): String = {
    val date = p.getText
    return CustomDateDeserializer.formatter.format(date);
  }
}

Требуется экспертная информация о том, как решить эту проблему

1 Ответ

1 голос
/ 04 марта 2020

, но не работает, говоря, что конструктор по умолчанию отсутствует

Вы получаете ошибку, потому что нет конструктора по умолчанию или пустого, если хотите, конструктора для классов case. В этом конкретном случае, когда вы объявляете, что case class MyPOJO(createdBy : LocalDateTime) scala компилятор сгенерирует что-то вроде (пример может быть не очень точным, я просто хочу показать идею):

class MyPOJO(createdBy : LocalDateTime) extends Product with Serializeble {
  override def hashCode(): Int = ...
  override def equals(oterh: Any): Boolean = ...
  override def toString(): String = ...
  // and other methods, like copy, unaply, tupled etc.
}

object MyPOJO {
  def apply(createdBy : LocalDateTime) = new MyPOJO(createdBy)
}

, поэтому Джексон не сможет создать пустой экземпляр класса с пустыми полями (или точнее null значениями), а затем ввести значения из источника JSON.

Что вы можете сделать - использовать обычный класс вместо case-классов. Или, что более предпочтительно, взглянуть на Scala дружественные JSON библиотеки, такие как Circe , которые не основаны на отражениях, в отличие от Джексона, и вместо этого генерируют JSON код c во время компиляции для некоторых классов, основанных на неявных макросах и Scala макросах (точнее, она опирается на библиотеку Shapeless, которая использует механизм макросов Scala под капотом).

В вашем конкретном случае код будет выглядеть следующим образом:

    import io.circe._
    import io.circe.generic.auto._
    import io.circe.syntax._

    case class MyPOJO(createdBy: LocalDateTime)
    val format = DateTimeFormatter.ofPattern("yyyy-MM-dd")

    // Implement own `Encoder` to render `LocalDateTime` as JSON string, separated with comma inside
    implicit val encoder: Encoder[LocalDateTime] = Encoder[String].contramap(_.format(format))

    // Implement own `Decoder` to parse JSON string as `LocalDateTime`
    implicit val decoder: Decoder[LocalDateTime] = Decoder[String].
      emapTry(value => Try(LocalDate.parse(value, format).atStartOfDay()))

    val foo = MyPOJO(LocalDateTime.now())
    val json = foo.asJson

    println(json.noSpaces)
    println(json.as[MyPOJO])

, который даст следующий результат:

{"createdBy":"2020-03-04"}
Right(MyPOJO(2020-03-04T00:00))

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...