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。转换的步骤是这样的:
- 通过 case class instance 获得所有 field name
- 通过这些 field name 配合 result set 的 resultSet("column name") 获得对应的 value,拼装成 map
- 将 map 转化到 json string
- jackson 把 json string 映射到 case class
虽说实现了转换,但是代码非常的 ugly。首先,我们要用到的是 case class instance 而不是 case class 本身,这意味着必须创建一个 instance,这个 instance 除了提供 field 信息以外就没用了,其次,创建 instance 本身需要了解 case class 的定义,因为需要写入到构造函数中,而上面转换器的目标就在于shapeless,在于通用,这不得不让我们为 case class 编写很多的 default value。再一个,还用到了 jackson,先到 string,再转回去,非常麻烦。
注意到几个问题:
- 从 row("date") 获取的 joda.LocaDate 在 idea 中声明的是 Any,但是它内在的类型属性是保持的,强制转换成 String 会得到一串很长的东西
- ObjectMapper 可以注册多个 module,他们在转换的时候用于序列化
- 获得 case class 的 field 信息,需要初始化一个 instance,其必须调用 getDeclaredFields 而不是 getFields。获得的属性按照声明顺序给出,是个array
- Field 通过 getName 获得属性名,getType 获得属性类型
joda time, jackson 与 scala 反射的更多相关文章
- 初识Scala反射
我们知道,scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射 ...
- 了解Scala反射
本篇文章主要让大家理解什么是Scala的反射, 以及反射的分类, 反射的一些术语概念和一些简单的反射例子. 什么是反射 我们知道, Scala是基于JVM的语言, Scala编译器会将Scala代码编 ...
- 一篇入门 -- Scala 反射
本篇文章主要让大家理解什么是Scala的反射, 以及反射的分类, 反射的一些术语概念和一些简单的反射例子. 什么是反射 我们知道, Scala是基于JVM的语言, Scala编译器会将Scala代码编 ...
- Scala反射(二)
我们知道,scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射 ...
- Scala - 处理时间(nscala-time - Joda Time的scala封装)
GITHUB : https://github.com/nscala-time/nscala-time MAVEN : (注意选对scala版本) <dependency> <gro ...
- Scala对class/object反射
近期有需求,要根据解析字符串,根据字符串的内容去调用方法.想到的基本就是使用反射.但是基本上能找到的资料,全没有讲scala的反射.只有零星点点的讲解.大部分都是用scala的语法写java反射最后翻 ...
- Scala进阶(1)—— 反射 object 和 class
1. Scala 的 反射 关于 Scala 反射的具体内容,可以参考官方文档:https://docs.scala-lang.org/overviews/reflection/overview.ht ...
- Scala的Json序列化
import java.util.TimeZone import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMappe ...
- 基于Spark和SparkSQL的NetFlow流量的初步分析——scala语言
基于Spark和SparkSQL的NetFlow流量的初步分析--scala语言 标签: NetFlow Spark SparkSQL 本文主要是介绍如何使用Spark做一些简单的NetFlow数据的 ...
随机推荐
- sqoop 常见错误以及处理方式
Oracle: Connection Reset Errors 错误代码 // :: INFO mapred.JobClient: Task Id : attempt_201105261333_000 ...
- IDEA 修改文件编码
Intellij Idea 修改 properties 文件编码 现象:idea 默认的properties文件是GBK,当有中文时,不同的客户端配置的编码不同时,可能产生中文乱码. 解决:修改pro ...
- Java设计模式(1)工厂模式(Factory模式)
工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...
- python 按照自然数排序遍历文件 python os.listdir sort by natural sorting
import os import re def sorted_aphanumeric(data): convert = lambda text: int(text) if text.isdigit() ...
- Linux入门教程:如何检查Linux系统的最后重启时间
问题: 是否有一个命令可以快速地检查系统已经运行了多久? 也就是我怎么知道Linux系统最后的重启时间? 有许多方法来查询系统最后的重启时间. 方法一 第一种方法是使用last命令. $ last r ...
- ie10以上媒体查询 css
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { }
- 错误 未能找到类型或命名空间名称"xxxxxx"的真正原因
今天又被这问题撞上了,结果神奇般的解决了 谷歌了很久都没有找到真正有用的解决方案,所以在这儿写下,让更多的人看到 最根本的原因其实就是引用的问题,引用错了,然后VS在这上面提示又不够智能,所以大家被坑 ...
- Xcode - 升级后模拟器无法响应电脑键盘
链接 Q: I used to be able to type with my real mac keyboard after launching the iPhone Simulator. Typi ...
- browser process request
What really happens when you navigate to a URL Beginner’s Guide: How IIS Process ASP.NET Request Wha ...
- CentOS 经常使用系统命令
# uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本号# cat /proc/cpuinfo # 查看CPU信息# ...