• joda time, jackson 与 scala 反射


    1. scala 反射,获得所有 field name

    可以直接从 case class 获得 field 而不必创建实例 (get fields of a class without an instance)

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

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

    2. Joda time  

    joda time 据称是 jdk1.8 以前最好的时间系统,我觉得 joda time 的确比 java 自带的时间系统好用。java 自带的时间系统需要花很大的功夫来处理格式的问题,time 与 calendar 也没结合到一起,印象中,每次处理时间问题起码要写三行代码。因用 asyn mysql db 引入 joda time,但在 joda time 与 json 的序列化和非序列化时遇到了问题。

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

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

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

    val str = JacksonUtils.objectMapper.writeValueAsString(mapping)

    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 获得属性类型
  • 相关阅读:
    日记
    没有起得晚的周末,希望今天能做一些什么
    怎么就这么喜欢测软件呢?—— Google Calendar农历问题
    Sharepoint带自定义属性的FieldType
    自己使用Outlook 2003 的一些小技巧
    Xml名称空间
    c# jingtailei 静态成员
    select count
    varchar nvarchar(转)
    linq 笔记(1)
  • 原文地址:https://www.cnblogs.com/xinsheng/p/4439464.html
Copyright © 2020-2023  润新知