github上的博客地址:

http://chuyun923.github.io/blog/2015/01/06/gsonyuan-ma-fen-xi/

XML和Json作为最常用的两种网络传输格式而被广泛使用,XML在早期数据传输中作为首选,但是近年来Json以其轻量级和更容易编写和解析而越来越流行,Gson作为google的一个开源Json解析框架提供了稳定和快速解析的功能,可以读读它的源代码了解一番。

说到Gson,其实它无非就是做两个工作,序列化(Object--->JsonString)和反序列化(JsonString--->Object),后文所说的两个方向从Object到String和String到Object的两个方向。可想而知,对于序列化来说,是较为容易的工作,而对于反序列化即Json解析才是Gson的重头戏。既然是对Json字符串的解析,那么少不了对Json字符串中的结构进行抽象。

Json抽象类

JsonElement

这是Json中元素的基类,它只提供了若干个类型判断的接口,简单判断这个Json元素的类型。以下几个类型都是它的子类。

1、JsonObject

包含多个JsonElement的集合,它在Json中对应这种类型的数据:

{
"count":100,
"users":[],
"paging":{
"offset":0,
"limit":10,
"hasMore":true
}
}

这个data是一个典型的JsonObject,它以{开头,其中包含了一些类似数值,数组,对象等其他JsonElement的内容。其实每一个Json字符串的根节点都是一个JsonObject。

JsonObject提供了比较多的方法来得到Json中的信息,addProperty()函数可以在当前Json节点下新建子结点。

2、JsonArray

JsonArray也表示JsonElement的集合,注意:Json中的数组并不要求所有的数据类型都一样

	[true,"hello"] //JsonArray,包括一个boolean和一个hello类型。

需要讨论的是JsonArray和JsonObject的区别是什么?从集合的角度来说,JsonObject中的JsonElement是无序的,而JsonArray中的集合元素是有序的,从直观感受来说,你可以通过下标来引用JsonArray中的元素,而JsonObject是通过键值对的方式来访问的,get("name")--->value

3、JsonPrimitive

对应Json中的基本类型,比如boolean,int,当然提供了基本类型和包装类的自动替换。

"count":100

4、JsonNull

空,对应null

"person":null

以上就是Gson对应Json结构的封装。

注解-Annotations

Expose

在对象进行序列化和反序列化的过程中,我们可以通过注解来屏蔽某一些字段。这个注解默认有两个参数,serializedeserialize都是默认true。如果设置为false,表示这个序列化(反)的过程中,这一个属性不需要进行处理。

通过Expose标注的属性在直接new Gson()的情况下不能生效,我们必须通过Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()来创建一个可以识别Expose注解的Gson。

小小的吐槽一把,这个地方的使用确实不太方便,举个栗子,一般来说,我们进行序列化的时候都是希望某一个属性不会序列化到Json字符里面(反之亦然),所以这里的一般思维是我要去处理这些特殊的属性。而如果你想通过Expose来去掉10个属性中的某一个,对不起,10个属性你都需要加上@Expose,然后对你想要处理的那个属性的Expose注解增加false参数,简直就是坑爹。。。。

//我想让Person类在序列化时,不去序列化password,是不是很坑爹?
class Person {
@Expose
private String userName;
@Expose (serialize = false)
private String passWord;
}

此外,和java本身的序列化一样,如果一个属性设置为transient或者static,那么两个序列化的两个方向上都会屏蔽掉这个属性,虽然比Expose简单,但是不够灵活。

SerializedName

这个注解使用较多,它会改变两个方向上这个属性的名称,在序列化是,JsonElement的键值会被替换成这个名字;解析时,Json中键值为这个名字的JsonElement会赋值给被注解的属性。

class Person {

@SerializedName(value = "A")
private int a = 1;
private int b = 2;
} //{"A":1,"b":2} 这个Json字符串和前面的Person等价

它使用场景最多的地方就是比如后端返回的json中的名称和我们定义的model类名称不一样时使用。

Since 和 Until

我们可以对我们的Model类进行序列化(两个方向)的版本控制,Since和Until刚好是两个相反的意义。

例子:

class Person {
@Since(value = 1.0) //GsonBuilder指定版本要从1.0开始的Gson才能解析
private int a = 1; @Until(value = 1.5) //GsonBuilder指定版本到1.5的Gson都可以解析,超过了不能解析
private int b = 2;
}

和Expose一样,要想Gson识别这两个注解,同样需要通过GsonBuilder.setVersion(double).create()来实现。

未完

Gson源码分析之Json结构抽象和注解使用的更多相关文章

  1. MySQL源码分析以及目录结构 2

    原文地址:MySQL源码分析以及目录结构作者:jacky民工 主要模块及数据流经过多年的发展,mysql的主要模块已经稳定,基本不会有大的修改.本文将对MySQL的整体架构及重要目录进行讲述. 源码结 ...

  2. MySQL源码分析以及目录结构

    原文地址:MySQL源码分析以及目录结构作者:jacky民工 主要模块及数据流经过多年的发展,mysql的主要模块已经稳定,基本不会有大的修改.本文将对MySQL的整体架构及重要目录进行讲述. 源码结 ...

  3. ffplay源码分析2-数据结构

    ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg提供的解码器和SDL库进行视频播放.本文基于FFmpeg工程4.1版本进行分析,其中ffplay源码清单如下: https://gith ...

  4. Springboot源码分析之项目结构

    Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...

  5. 鸿蒙源码分析系列(总目录) | 百万汉字注解 百篇博客分析 | 深入挖透OpenHarmony源码 | v8.23

    百篇博客系列篇.本篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51.c.h .o 百篇博客.往期回顾 在给OpenHarmony内核源码加注过程中,整理出以下 ...

  6. jQuery1.11源码分析(6)-----jQuery结构总揽

    (在看以下内容之前请先对原型链有一定的了解,比如:prototype是对象还是函数?) 在看jQuery的其他源码之前,必须对jQuery的数据结构有一定的了解. jQuery的核心很简单,jQuer ...

  7. kibana5.6源码分析3--目录结构

    kibana5.6的项目目录结构: bin:系统启动脚本目录 config:kibana配置文件目录 data:估计是缓存一些系统数据的,uuid放在这里面 docs: maps:此目录包含TileM ...

  8. Vue.js 源码分析(一) 代码结构

    关于Vue vue是一个兴起的前端js库,是一个精简的MVVM.MVVM模式是由经典的软件架构MVC衍生来的,当View(视图层)变化时,会自动更新到ViewModel(视图模型),反之亦然,View ...

  9. nginx源码分析—内存池结构ngx_pool_t及内存管理

    Content 0. 序 1. 内存池结构 1.1 ngx_pool_t结构 1.2 其他相关结构 1.3 ngx_pool_t的逻辑结构 2. 内存池操作 2.1 创建内存池 2.2 销毁内存池 2 ...

随机推荐

  1. C语音指针Introduction.

    指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指针变量可以表示各种数据结构: 能很方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序 ...

  2. rhel Linux 网络配置

    --网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 1)DHCPDEVICE=eth0BOOTPROTO=dhcpONBOOT=yes2)静态IP  ...

  3. MiniUI学习笔记1

    1.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  4. java下文件遍历,与删除

    package cn.stat.p1.file; import java.io.File; public class newfilelist { /** * @param args */ public ...

  5. 一、webpack那点事-安装、环境搭建

    前言: 还记得两年前刚来公司才几个月,经理就安排我去做JS地图相关的维护和开发工作,然后就跟着一个公司老鸟(没俩月他离职了)熟悉地图相关的功能. 本人嘛,那会前端JS实际开发经验也才几个月,然后当我看 ...

  6. cas+tomcat+shiro实现单点登录-3-CAS服务器深入配置(连接MYSQL)

    目录 1.tomcat添加https安全协议 2.下载cas server端部署到tomcat上 3.CAS服务器深入配置(连接MYSQL) 4.Apache Shiro 集成Cas作为cas cli ...

  7. TCP/IP 要点备忘

    1. 3次握手/4次挥手过程,以及状态变化: 2. RTT,TTL,TOS(8位服务类型,最小延时.最大吞吐.最高可用.最小费用). 3. TimeWait(2msl)状态,防止最后一个ack丢失 4 ...

  8. uva 846 - Steps

    找出步數與距離的關係即可得解. 0步最多能抵達的距離是0 1步最多能抵達的距離是1(1) 2步最多能抵達的距離是2(1 1) 3步最多能抵達的距離是4(1 2 1) 4步最多能抵達的距離是6(1 2 ...

  9. sql_autoload_register() 函数 和__autoload() 的区别

    1:__autoload($class) 因为是一个函数,所以只能定义一次,使用多个会冲突报错;而 sql_autoload_register('function') 可定义多个,它有效地创建一个队列 ...

  10. HTML&CSS基础学习笔记1.10—添加链接

    我们可以设置链接的目标,使我们点击后可以跳转到我们想要去的地方. <a>标签的 href 属性用于指定超链接目标的 URL. 在页面中添加的<a>标签,浏览器会用特殊效果显示, ...