joda time, jackson 與 scala 反射

1. scala 反射,得到全部 field namejava

能夠直接從 case class 得到 field 而沒必要建立實例 (get fields of a class without an instance)mysql

def extractFieldNames[T<:Product:Manifest] = {
  implicitly[Manifest[T]].erasure.getDeclaredFields.map(_.getName)
sql

case class Person(name:String, age:Int)
scala> extractFieldNames[Person]
res4: Array[java.lang.String] = Array(name, age)
json

 

2. Joda time  app

joda time 據稱是 jdk1.8 之前最好的時間系統,我以爲 joda time 的確比 java 自帶的時間系統好用。java 自帶的時間系統須要花很大的功夫來處理格式的問題,time 與 calendar 也沒結合到一塊兒,印象中,每次處理時間問題起碼要寫三行代碼。因用 asyn mysql db 引入 joda time,但在 joda time 與 json 的序列化和非序列化時遇到了問題。less

 

val res = Tag(new LocalDate, "id", "tag")ide

val names = res.getClass.getDeclaredFields.map(field => field.getName)函數

val mapping = names.map(name => (name -> row(name))).toMapidea

val str = JacksonUtils.objectMapper.writeValueAsString(mapping)spa

val ins = JacksonUtils.objectMapper.readValue(str, classOf[Tag])

 

joda time 的 toString 並不簡單,好比LocalDate類型的 "2014-05-05" 轉化到 json 後會有很長一串數據,再從 json 轉到 joda time,jackson 報錯,序列化有問題了。

在 jackson 2.0 (也就是 fastxml)之後,處理 joda time 有一種很簡單的作法,就是直接註冊 joda time module 到 jackson mapper

 

val objectMapper = new ObjectMapper()
objectMapper.registerModule(DefaultScalaModule)
objectMapper.registerModule(new JodaModule)

 

3. Jackson 註冊 Module 用於序列化

同時也瞭解到,objectMapper 能夠一次註冊多個 module,這種可拔插的設計用起來真的很舒心。 

在第一段代碼中,用到了 scala 反射機制。其實這段代碼的主要目標是編寫一個簡單的數據轉換器,從 mysql resultSet 轉到 case class。轉換的步驟是這樣的:

  1. 經過 case class instance 得到全部 field name
  2. 經過這些 field name 配合 result set 的 resultSet("column name") 得到對應的 value,拼裝成 map
  3. 將 map 轉化到 json string
  4. jackson 把 json string 映射到 case class

雖然說實現了轉換,可是代碼很是的 ugly。首先,咱們要用到的是 case class instance 而不是 case class 自己,這意味着必須建立一個 instance,這個 instance 除了提供 field 信息之外就沒用了,其次,建立 instance 自己須要瞭解 case class 的定義,由於須要寫入到構造函數中,而上面轉換器的目標就在於shapeless,在於通用,這不得不讓咱們爲 case class 編寫不少的 default value。再一個,還用到了 jackson,先到 string,再轉回去,很是麻煩。

 

注意到幾個問題:

  1. 從 row("date") 獲取的 joda.LocaDate 在 idea 中聲明的是 Any,可是它內在的類型屬性是保持的,強制轉換成 String 會獲得一串很長的東西
  2. ObjectMapper 能夠註冊多個 module,他們在轉換的時候用於序列化
  3. 得到 case class 的 field 信息,須要初始化一個 instance,其必須調用 getDeclaredFields 而不是 getFields。得到的屬性按照聲明順序給出,是個array
  4. Field 經過 getName 得到屬性名,getType 得到屬性類型
相關文章
相關標籤/搜索