Scala Jackson 使用经验总结

背景

主要记录 scala 使用 jackson 中的几个问题

  • long 型数据转换为 ZonedDateTime
  • 对 field 做自定义反序列化

以下面对 json 为例

1
2
3
4
{
"time": 1570712743943, //time 为 Long ,反序列化需要映射成 ZonedDateTime
"id": 1 // id 为 Integer,反序列化成 String
}

scala 代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.time.ZonedDateTime

import com.fasterxml.jackson.annotation.JsonInclude.Include
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.{DeserializationContext, DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import org.scalatest.FunSuite

class TestJackson extends FunSuite {
lazy val mapper = {
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(new JavaTimeModule())
mapper.setSerializationInclusion(Include.NON_NULL)
mapper.setSerializationInclusion(Include.NON_ABSENT)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.registerModule(DefaultScalaModule)
mapper
}

test("jackson") {
val json =
"""
|{
| "time": 1570712743943,
| "id": 1
|}
|""".stripMargin

val t = mapper.readValue(json, classOf[Test])

println(s"time type: ${t.time.getClass.getSimpleName}")
println(s"id type: ${t.id.getClass.getSimpleName}")
}

}

class IdDeserializer() extends StdDeserializer[String](classOf[String]) {
override def deserialize(p: JsonParser, ctxt: DeserializationContext): String = {
p.getValueAsString
}
}

case class Test(time: ZonedDateTime, @JsonDeserialize(using = classOf[IdDeserializer]) id: String)

输出为

1
2
time type: ZonedDateTime
id type: String

回到问题

  • long 型数据转换为 ZonedDateTime

    • 通过 new JavaTimeModule() 来实现 java8 中特有的 ZonedDateTime 的映射
  • 对 field 实现自定义反序列化

    • 通过 @JsonDeserialize(using = classOf[IdDeserializer]) 指定需要自定义反序列化的 field
    • 通过 class IdDeserializer().deserialize 实现反序列化的逻辑

备注

sbt dependencies

1
2
3
4
5
val jackson = Seq(
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.9",
"com.fasterxml.jackson.datatype" % "jackson-datatype-jdk8" % "2.9.9",
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9"
)