[英]Custom serialization and deserialization is scala using jackson
我有一个 JSON 作为字符串,我将其反序列化并实例化为 Scala 的 MyPOJO 案例类。 我的数据是 YYYY-MM-DD 格式,但 POJO createdBy 中的实际属性是 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);
}
}
需要专家输入如何解决这个问题
但没有工作,说缺少默认构造函数
您收到错误消息,因为如果您愿意,案例类的构造函数没有默认值或空值。 在这种特殊情况下,当您声明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 注入值。
您可以做什么 - 使用普通类而不是案例类。 或者,更可取的是,看看像Circe这样的 Scala 友好的 JSON 库,它不是基于反射的,与 Jackson 不同,而是在编译时为某些类生成 JSON 编解码器,基于隐式和 Scala 宏(更准确地说,它依赖于在Shapeless
使用 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))
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.