java - 自定义序列化和反序列化是使用 jackson 的 scala

标签 java scala jackson

我有一个 JSON 作为字符串,我将其反序列化并实例化为 scala 的 MyPOJO 案例类。我的数据是 YYYY-MM-DD 格式,但 POJO createBy 中的实际属性是 LocalDateTime。

如何在实例化 Pojo 时分配默认时间值 2020-03-02 00:00:00,

序列化应返回 yyyy-mm-dd 格式。我的序列化和反序列化格式不同。

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);
  }
}

需要专家提供有关如何解决此问题的意见

最佳答案

but is not working saying default constructor is missing

您收到错误,因为案例类没有默认或空的构造函数(如果您愿意的话)。在这种特殊情况下,当您声明 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)
}

因此 Jackson 将无法创建具有空字段(或更准确地说是 null 值)的空类实例,然后从源 JSON 注入(inject)值。

你可以做什么 - 使用普通类而不是案例类。或者,更可取的是查看 Scala 友好的 JSON 库,例如 Circe与 Jackson 不同,它不是基于反射的,而是基于隐式宏和 Scala 宏在编译时为某些类生成 JSON 编解码器(更准确地说,它依赖于在幕后使用 Scala 宏机制的 Shapeless 库) )。

在您的特定情况下,代码如下所示:

    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))

希望这有帮助!

关于java - 自定义序列化和反序列化是使用 jackson 的 scala,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60501503/

相关文章:

java - 使用 Jackson 对 JSON 文件进行多态反序列化

Java:连接到 psql 数据库会引发错误(ClassNotFoundException)

java - Spring Data Rest - 隐藏而不是暴露 ID

java - org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure : Could not find MessageBodyWriter for response object of type: of media type: application/xml

java - 使用play-framework 2.5连接MySQL数据库

scala - 我怎样才能使这个方法更具可扩展性

scala - 如何将Apache Spark日志从驱动程序和从属服务器重定向到使用log4j启动Spark作业的计算机的控制台?

java - 无法写入内容: No serializer found for class org. springframework.context.expression.StandardBeanExpressionResolver

java - 在客户端映射 Web 服务端点的最佳实践

java - servlet 容器是否应该为每个传入请求创建新的 javax.servlet.http.HttpServlet 实例?