到目前为止,Scala 环境下至少存在6种 Json 解析的类库,这里面不包括 Java 语言实现的 Json 类库。所有这些库都有一个非常相似的抽象语法树(AST)。而 json4s 项目旨在提供一个单一的 AST 树供其他 Scala 类库来使用。

json4s 的使用非常的简单,它可以将类直接转换成 json 格式输出,也支持将 json 格式的数据转换成 class 对象。对于 Scala 和 Java 常见的类型(比如String、Int、java.lang.Integer、java.lang.Long、java.lang.Boolean 等)都提供了相应的转换函数。比如下面我们直接将一个类转换成 json:

import org.json4s.JsonAST.{JNull, JString}
import org.json4s.{DefaultFormats, Extraction, Formats}
import org.json4s.jackson.JsonMethods.render
import org.json4s.jackson.JsonMethods.pretty case class Person(name: String, age: Int)
implicit val formats: Formats = DefaultFormats val person = Person("iteblog", )
val jvalue = Extraction.decompose(person) println(pretty(render(jvalue))) 输出
{
"name" : "iteblog",
"age" :
}

同时我们也可以直接将一个 json 对象转换成类对象:

val person =  Extraction.extract[Person](jvalue)
println(person) 输出
Person(iteblog,)

我们可以看到上面的例子使用起来都很简单的。但是如果碰到元素的类型在 json4s 中没有事先定义,结果会怎么样呢?比如在 json4s 中并没有定义对 java.sql.Date 类型的解析,那如果我们用到了这个类型,会出现什么问题呢?具体如下:

case class Person(name: String, age: Int, birthday: Date)
implicit val formats: Formats = DefaultFormats val person = Person("iteblog", , Date.valueOf("2019-07-01"))
val jvalue = Extraction.decompose(person) println(pretty(render(jvalue))) 输出 {
"name" : "iteblog",
"age" : ,
"birthday" : { }
}

可以从上面的结果看出,json4s 并没有正确的解析出 birthday 字段的值。 如果我们将 json 解析到类中,会出现什么问题呢?

val jvalue1 = parse("""{"name" : "iteblog", "age" : 110, "birthday" : "--"}""")
val person = Extraction.extract[Person](jvalue1)
println(person)

结果

Exception in thread "main" org.json4s.package$MappingException: No usable value for birthday
Parsed JSON values do not match with class constructor
args=
arg types=
executable=Executable(Constructor(public java.sql.Date(int,int,int)))
cause=wrong number of arguments
types comparison result=MISSING(int),MISSING(int),MISSING(int)
at org.json4s.reflect.package$.fail(package.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$.apply(Extraction.scala:)
at org.json4s.Extraction$ClassInstanceBuilder$$anonfun$.apply(Extraction.scala:)
at scala.collection.TraversableLike$$anonfun$map$.apply(TraversableLike.scala:)
at scala.collection.TraversableLike$$anonfun$map$.apply(TraversableLike.scala:)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:)
at scala.collection.AbstractTraversable.map(Traversable.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:)
at org.json4s.Extraction$$anonfun$extract$.apply(Extraction.scala:)
at org.json4s.Extraction$$anonfun$extract$.apply(Extraction.scala:)
at org.json4s.Extraction$.customOrElse(Extraction.scala:)
at org.json4s.Extraction$.extract(Extraction.scala:)
at org.json4s.Extraction$.extract(Extraction.scala:)
at com.iteblog.Test$.main(Test.scala:)
at com.iteblog.Test.main(Test.scala)
Caused by: org.json4s.package$MappingException: Parsed JSON values do not match with class constructor
args=
arg types=
executable=Executable(Constructor(public java.sql.Date(int,int,int)))
cause=wrong number of arguments
types comparison result=MISSING(int),MISSING(int),MISSING(int)
at org.json4s.reflect.package$.fail(package.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.instantiate(Extraction.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.result(Extraction.scala:)
at org.json4s.Extraction$$anonfun$extract$.apply(Extraction.scala:)
at org.json4s.Extraction$$anonfun$extract$.apply(Extraction.scala:)
at org.json4s.Extraction$.customOrElse(Extraction.scala:)
at org.json4s.Extraction$.extract(Extraction.scala:)
at org.json4s.Extraction$ClassInstanceBuilder.org$json4s$Extraction$ClassInstanceBuilder$$buildCtorArg(Extraction.scala:)
... more

可以看出,出现无法解析出 birthday 字段,因为 json4s 并没有提供将字符串解析到 java.sql.Date。那怎么办呢?json4s 为我们提供了自定义解析类型的方法,那就是 CustomSerializer,我们只需要继承这个类,并实现对自定义类型的序列化和反序列化的方法即可。那对我们的例子可以实现如下:

package com.iteblog

import java.sql.Date

import org.json4s.JsonAST.{JNull, JString}
import org.json4s.{CustomSerializer, DefaultFormats, Extraction, Formats}
import org.json4s.jackson.JsonMethods.render
import org.json4s.jackson.JsonMethods.pretty
import org.json4s.jackson.JsonMethods.parse object Iteblog { case class Person(name: String, age: Int, birthday: Date) case object DateSerializer extends CustomSerializer[Date](_ => ( {
case JString(s) => Date.valueOf(s)
case JNull => null
}, {
case d: Date => JString(d.toString)
})) def main(args: Array[String]): Unit = { implicit val formats: Formats = DefaultFormats + DateSerializer val person = Person("iteblog", , Date.valueOf("2019-07-01"))
val jvalue = Extraction.decompose(person) println(pretty(render(jvalue))) val jvalue1 = parse("""{"name" : "iteblog", "age" : 110, "birthday" : "--"}""")
val r = Extraction.extract[Person](jvalue1)
println(r)
}
}

输出

{
"name" : "iteblog",
"age" : ,
"birthday" : "2019-07-01"
}
Person(iteblog,,--)

可见,通过自定义的 DateSerializer 我们可以解析 java.sql.Date 类型了。

在 json4s 中自定义CustomSerializer的更多相关文章

  1. Html中自定义鼠标的形状

    Html中自定义鼠标的形状 <html> <head> <title>自定义的鼠标形状</title> <meta http-equiv=&quo ...

  2. 教你一招:在PowerPoint中自定义可输入文本的占位符

    日常生活中,当我们设计多媒体课件时,默认的版式其实已经够用了.但是,很多时候,我们需要更加个性一点,所以,我们需要自定义很多东西.本文介绍在PowerPoint中自定义可输入文本的占位符. 一.占位符 ...

  3. android代码优化----ListView中自定义adapter的封装(ListView的模板写法)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  4. 在Eclipse中自定义类似syso的快捷代码模板

    sysout/syso syserr/ syse 点击菜单栏的“Window”->“Preferences”,打开“Preferences”对话框.在Preferences”对话框中点击“Jav ...

  5. 在.net桌面程序中自定义鼠标光标

    有的时候,一个自定义的鼠标光标能给你的程序增色不少.本文这里介绍一下如何在.net桌面程序中自定义鼠标光标.由于.net的桌面程序分为WinForm和WPF两种,这里分别介绍一下. WinForm程序 ...

  6. .net中自定义过滤器对Response内容进行处理

    原文:http://www.cnblogs.com/zgqys1980/archive/2008/09/02/1281895.html 代码DEMO:http://files.cnblogs.com/ ...

  7. SharePoint 2013 中自定义WCF服务

    在使用SharePoint2013的时候,如果其他客户端 API 的组合不足,可以通过自定义 Web 服务扩展 SharePoint.默认情况下,SharePoint 2013 不仅支持创建自定义 A ...

  8. 浅析在QtWidget中自定义Model

    Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的model接 ...

  9. VBA中自定义类和事件的(伪)注册

    想了解一下VBA中自定义类和事件,以及注册事件处理程序的方法. 折腾了大半天,觉得这样的方式实在称不上“注册”,所以加一个“伪”字.纯粹是瞎试,原理也还没有摸透.先留着,有时间再接着摸. 做以下尝试: ...

随机推荐

  1. 一键配置树莓派wifi、静态ip等

    系统老是被我玩坏,重新烧录系统后配置又太麻烦,用shell脚本一键配置一下wifi和静态IP #!/bin/bash touch /media/fanghaoyu/boot/ssh echo &quo ...

  2. Vuex之store仓库计算属性Getter

    (1)简介 Getter相当于vue中的computed计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,这里可以通过定义vuex的Getter来获 ...

  3. Java并发编程-JUC-CountDownLatch 倒计数门闩器-等待多线程完成再放行 -一次性使用

    如题 (总结要点) CountDownLatch 倒计数门闩器, 让1-n-1个线程等待其他多线程完成工作. (Excel的多个Sheet的解析,最终等待解析完毕后;要实现主线程等待所有线程完成she ...

  4. solr中特殊字符的处理

    如查询的条件为:params.add("fq", "jiucaiyun_brand:Double A" ),这样是查不出带有空格的条件,需要把空格转义 if(b ...

  5. 没有内置小鹤双拼的rime输入法就是差劲

    没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体~ 没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体~ 没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体 ...

  6. Js 日期字符串分别截取 年 月 日 时 分 秒

    function shijiantime(times){ var timearr = times.replace(" ", ":").replace(/\:/g ...

  7. Ansible自动部署tomcat

    1.首先准备3台机器 ansible机器:192.168.52.34 目标主机:192.168.52.35 目标主机:192.168.52.36 2.关闭防火墙 [root@localhost ~]# ...

  8. MongoDB远程连接-命令行客户端mongo.exe

    命令行客户端mongo.exe 位于安装目录bin子目录下.MongoDB的所有可执行程序都在其中. 双击打开mongo.exe应该是默认连接本地数据库服务,因此需要用Cmd或Powershell的方 ...

  9. Reactive Extensions (Rx) 入门(3) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7628322 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  10. 第10组 Alpha冲刺(1/4)

    队名:凹凸曼 组长博客 作业博客 组员实践情况 童景霖 过去两天完成了哪些任务 文字/口头描述 学习Android studio和Java,基本了解APP前端的制作 完善项目APP原型 展示GitHu ...