Java 中 Gson的使用

JSON 是一种文本形式的数据交换格式,它比XML更轻量、比二进制容易阅读和编写,调式也更加方便;解析和生成的方式很多,Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等

一、Gson的基本用法

  Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化;同时每个方法都提供了重载方法

(1)基本数据类型的解析

Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class);  //99.99
boolean b = gson.fromJson("true", boolean.class);     // true
String str = gson.fromJson("String", String.class);   // String

(2)基本数据类型的生成

Gson gson = new Gson();
String jsonNumber = gson.toJson(100);       // 100
String jsonBoolean = gson.toJson(false);    // false
String jsonString = gson.toJson("String"); //"String"

(3)POJO类的生成与解析

public class User {
    //省略其它
    public String name;
    public int age;
    public String emailAddress;
}

生成JSON:

Gson gson = new Gson();
User user = new User("张三",24);
String jsonObject = gson.toJson(user); // {"name":"张三kidou","age":24}

解析JSON:

Gson gson = new Gson();
String jsonString = "{\"name\":\"张三\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);

二、属性重命名 @SerializedName 注解的使用

从上面POJO的生成与解析可以看出json的字段和值是的名称和类型是一一对应的,但也有一定容错机制(如第一个例子第3行将字符串的99.99转成double型),但有时候也会出现一些不和谐的情况,如:

  期望的json格式:{"name":"张三","age":24,"emailAddress":"[email protected]"}

  实际:{"name":"张三","age":24,"email_address":"[email protected]"}

  Gson在序列化和反序列化时需要使用反射,一般各类库都将注解放到annotations包下,打开源码在com.google.gson包下有一个annotations,里面有一个SerializedName的注解类。对于json中email_address这个属性对应POJO的属性则变成: 

@SerializedName("email_address")
public String emailAddress;

  为POJO字段提供备选属性名SerializedName注解提供了两个属性,上面用到了其中一个,别外还有一个属性alternate,接收一个String数组

  注:alternate需要2.4版本

@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
//当三个属性(email_address、email、emailAddress)都中出现任意一个时均可以得到正确的结果

//当多种情况同时出时,以最后一个出现的值为准。
Gson gson = new Gson();
String json = "{\"name\":\"张三kidou\",\"age\":24,\"emailAddress\":\"[email protected]\",\"email\":\"[email protected]\",\"email_address\":\"[email protected]\"}";
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // [email protected]

三、Gson中使用泛型

  例如:JSON字符串数组:["Android","Java","PHP"]

  当要通过Gson解析这个json时,一般有两种方式:使用数组,使用List;而List对于增删都是比较方便的,所以实际使用是还是List比较多

  数组比较简单:

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class)

  对于List将上面的代码中的 String[].class 直接改为 List<String>.class 是不行的,对于Java来说List<String> 和List<User> 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除

  为了解决的上面的问题,Gson提供了TypeToken来实现对泛型的支持,所以将以上的数据解析为List<String>时需要这样写

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
//TypeToken的构造方法是protected修饰的,所以上面才会写成new TypeToken<List<String>>() {}.getType() 而不是 new TypeToken<List<String>>().getType()

  泛型解析对接口POJO的设计影响

    泛型的引入可以减少无关的代码:  

{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}

    我们真正需要的data所包含的数据,而code只使用一次,message则几乎不用,如果Gson不支持泛型或不知道Gson支持泛型的同学一定会这么定义POJO

public class UserResponse {
    public int code;
    public String message;
    public User data;
}

    当其它接口的时候又重新定义一个XXResponse将data的类型改成XX,很明显code,和message被重复定义了多次,通过泛型可以将code和message字段抽取到一个Result的类中,这样只需要编写data字段所对应的POJO即可:

public class Result<T> {
    public int code;
    public String message;
    public T data;
}
//对于data字段是User时则可以写为 Result<User> ,当是个列表的时候为 Result<List<User>>

四、Gson的流式反序列化

  (1)自动方式

    Gson提供了fromJson()和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法 

Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);

  (2)手动方式:手动的方式就是使用stream包下的JsonReader类来手动实现反序列化,和Android中使用pull解析XML是比较类似的

String json = "{\"name\":\"张三\",\"age\":\"24\"}";
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject();
while (reader.hasNext()) {
    String s = reader.nextName();
    switch (s) {
        case "name":
        user.name = reader.nextString();
        break;
        case "age":
        user.age = reader.nextInt(); //自动转换
        break;
        case "email":
        user.email = reader.nextString();
        break;
    }
}
reader.endObject(); // throws IOException
System.out.println(user.name);  //张三
System.out.println(user.age);   // 24
System.out.println(user.email); //[email protected]

自动方式最终都是通过JsonReader来实现的,如果第一个参数是String类型,那么Gson会创建一个StringReader转换成流操作

五、Gson的流式序列化

  (1)自动方式

  Gson.toJson方法列表

  //PrintStream(System.out) 、StringBuilder、StringBuffer和*Writer都实现了Appendable接口。  

Gson gson = new Gson();
User user = new User("张三",24,"[email protected]");
gson.toJson(user,System.out);

(2)手动方式

JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject() // throws IOException
    .name("name").value("张三")
     .name("age").value(24)
     .name("email").nullValue() //演示null
    .endObject(); // throws IOException
    writer.flush(); // throws IOException
//{"name":"张三","age":24,"email":null}
//除了beginObject、endObject还有beginArray和endArray,两者可以相互嵌套,注意配对即可。beginArray后不可以调用name方法,//同样beginObject后在调用value之前必须要调用name方法。

六、 使用GsonBuilder导出null值、格式化输出、日期时间

  一般情况下Gson类提供的 API已经能满足大部分的使用场景,但有时需要更多特殊、强大的功能时,这时候就引入一个新的类 GsonBuilder。

GsonBuilder从名上也能知道是用于构建Gson实例的一个类,要想改变Gson默认的设置必须使用该类配置Gson

  GsonBuilder用法: 

//各种配置  //生成配置好的Gson
Gson gson = new GsonBuilder().create();

(1)Gson在默认情况下是不动导出值null的键的,如:

public class User {

     public String name;
     public int age;
   //省略
     public String email;

}
Gson gson = new Gson();
User user = new User(张三",24);
System.out.println(gson.toJson(user)); //{"name":"张三","age":24}
//email字段是没有在json中出现的,当在调试时需要导出完整的json串时或API接中要求没有值必须用Null时,就会比较有用。

格式化输出、日期时间及其它:

Gson gson = new GsonBuilder()
    //序列化null
    .serializeNulls()
    // 设置日期时间格式,另有2个重载方法
    // 在序列化和反序化时均生效
    .setDateFormat("yyyy-MM-dd")
    // 禁此序列化内部类
     .disableInnerClassSerialization()
    //生成不可执行的Json(多了 )]}‘ 这4个字符)
    .generateNonExecutableJson()
     //禁止转义html标签
    .disableHtmlEscaping()
    //格式化输出
    .setPrettyPrinting()
    .create();
//:内部类(Inner Class)和嵌套类(Nested Class)的区别

Gson的使用--使用注解

1.自定义字段的名字

@SerializedName("w");
int width

2.定义那些字段需要被序列化或者反序列化

注意,在Java中,所有用transient声明的字段,都不会被Gson序列化和反序列化

Gson提供了注解来分别的控制某一个字段是否需要被序列化或者反序列化。对序列化和反序列化分开控制。

使用@Expose注解,我们可以对序列化和反序列化单独控制,该注解有两个值,分别是deserialize和serialize,比如如下的例子

public class Account {

  //声明该字段不参与反序列化
  @Expose(deserialize = false)
  private String accountNumber;

  //只要有一个字段使用了Expose注解,所有需要参与序列化和反序列化的字段都要有这个注解
  //因为这个注解要么不生效,如果生效的话,就只会对有Expose注解的字段进行处理。
  @Expose
  private String iban;

  //声明该字段不参与序列化
  @Expose(serialize = false)
  private String owner;

  //声明该字段序列化和反序列化都不参与
  @Expose(serialize = false, deserialize = false)
  private String address;

  private String pin;
}

要使该注解生效,必须对Gson进行配置,如下

GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();

如果我们不对Gson进行配置的话,该注解就不会生效,这样就会默认所有的字段都会被序列化和反序列化。

3.对Java Bean进行版本控制,这个使用的很少,比如

public class SoccerPlayer {

  private String name;

  //表明这个属性是1.2版本之后才加入的
  @Since(1.2)
  private int shirtNumber;

  //表明这个属性在0.9版本上已经被移除了
  @Until(0.9)
  private String country;

  private String teamName;

  // Methods removed for brevity
}

和Expose一样,要使用这两个注解,也需要对Gson进行配置,如下

GsonBuilder builder = new GsonBuilder();
//在这里,我们定义版本是1.0,由于shirtNumber在1.2才加入,所以不生效
//country在0.9被移除,所以也不生效
builder.setVersion(1.0);
Gson gson = builder.create()

原文地址:https://www.cnblogs.com/deityjian/p/11080212.html

时间: 2024-08-30 15:22:56

Java 中 Gson的使用的相关文章

Java中json工具对比分析

Java中几个json工具分析 1, 环境 JDK1.6+IDE(IntelliJ IDEA)+windowsXP+GBK编码 2,分析对象 jackson1.8.2 http://jackson.codehaus.org/ gson1.7.1 http://code.google.com/p/google-gson/ jsob_lib2.4 http://json-lib.sourceforge.NET/ 3,使用实例          用两个bean进行测试,两个bean都嵌套有数组和对象,

java中的使用锯齿进行类别管理和json交互

java中提供锯齿数据,某些时候特别有用,比如用groupid映射userid.在无论涉及到http数据还是json数据保存护着传输. public static void main(String[] args) {   //使用在json数据转换中      int[][] groups = new int[3][];    groups[0] = new int[]{1,3,4,5};    groups[1] = new int[]{6,2};    groups[2] = new int

Java中关于Json对象类型和字符串类型之间互相转化的问题

Java中关于Json格式转化Object,Map,Collection类型和String类型之间的转化在我们实际项目中应用的很是普遍和广泛.最近工作的过程中也是经常有,因此,自己封装了一个JsonUtil.java类. 所需要的jar包:slf4j-jdk14-1.5.6.jar,slf4j-api-1.5.6.jar------>此两个jar包是slf4j日志jar包 jackson-annotations-2.1.1.jar,jackson-core-2.1.1.jar,jackson-d

JAVA中使用JSON进行数据传递

在接口的访问和数据的传输方面使用的比较多的是使用JSON对象来操作格式化数据:在服务器端采用JSON字符串来传递数据并在WEB前端或者Android客户端使用JSON来解析接收到的数据. 首先,在JAVA中使用JSON需要引入 org.json 包(点击 这里 可以下载相应的JAR包!), 并在程序中引入相应的JSON类: import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; 其

Java中常用的JSON工具

1.Java中常用的JSON工具 Gson: 谷歌开发的 JSON 库,功能十分全面. FastJson: 阿里巴巴开发的 JSON 库,性能十分优秀. Jackson: 社区十分活跃且更新速度很快. 2.以下教程基于 FastJson 讲解. 在 Maven 构建的项目中,在 pom.xml 文件中加入以下依赖即可. <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</a

java中的三元运算符详解

最近在带领实习生中遇到很多新手问与三元运算符有关的java题目,多数为代码结果题,少数为应用题.鉴于很多资料上对于java三元运算的讲解过于简单,网上的资料与题目也不是很完善,对于结果答案分析不一,故在此总结,当然仅为个人观点,水平有限,不足之处,还请大家多多指出,互相交流学习. 什么是java三元运算符呢?无疑其操作元有三个,第一个是条件表达式,剩余两个为值,条件表达式为真时运算取第一个值,为假时取第二个值. 其示例代码如下:boolean a = 20 < 45 ? true : false

java中BigDecimal的学习

干着java的活,但是看的都是一些偏底层的东西(或者我根本就没有看),有点荒废了java的学习. 最近一直在用到一个类是BigDecimal,但都是模棱两可地在那儿用,并没有深入研究这个类的细节,感觉不能再拖了. BigDecimal,从名字来看就是进行大数运算的,不光这样,还广泛用于小数的精确运算. 当你接触到和钱有关的计算的时候,这个类还是很有用滴. 先来看一个例子 1 package com.tuhooo.bigdecimal; 2 3 /** 4 * Created by tuhooo

Java 中几个重要的关键字

Java中的关键字特别多,大致如下: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements interface native new static strictfp synchronized transient volatile 程序控制 break continue return do while if else for instanceof switch case default 异常

深入剖析Java中的装箱和拆箱

阅读目录 一.什么是装箱?什么是拆箱?二.装箱和拆箱是如何实现的三.面试中相关的问题 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 回到顶部 一.什么是装箱?什么是拆箱? 我们知道 Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE5之前,如果要生成