Java对象和Json之间的互转,一般用的比较多的两个类库是Jackson和Gson,下面记录一下Gson的学习使用。
基础概念 Serialization:序列化,使Java对象到Json字符串的过程。 Deserialization:反序列化,字符串转换成Java对象
JSON数据中的JsonElement有下面这四种类型 
JsonPrimitive —— 例如一个字符串或整型 JsonObject—— 一个以 JsonElement 名字(类型为 String)作为索引的集合。也就是说可以把 JsonObject 看作值为 JsonElement 的键值对集合。 JsonArray—— JsonElement 的集合。注意数组的元素可以是四种类型中的任意一种,或者混合类型都支持。 JsonNull—— 值为null
 
依赖引用 使用Maven管理Gson,pom.xml导入gson的依赖
1 2 3 4 5 <dependency >     <groupId > com.google.code.gson</groupId >     <artifactId > gson</artifactId >     <version > 2.3.1</version > </dependency > 
 
基本语法 Gson的两个基础方法
 
Gson中的一些注解 1 @SerializedName注解 该注解能指定该字段在JSON中对应的字段名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  class  Box  {   @SerializedName("w")    private  int  width;   @SerializedName("h")    private  int  height;   @SerializedName("d")    private  int  depth;    }
 
也就是说{"w":10,"h":20,"d":30} 这个JSON 字符串能够被解析到上面的width,height和depth字段中。
2 @Expose注解 该注解能够指定该字段是否能够序列化或者反序列化,默认的是都支持(true)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  class  Account  {   @Expose (deserialize = false )   private  String  accountNumber;   @Expose    private  String  iban;   @Expose (serialize = false )   private  String  owner;   @Expose (serialize = false , deserialize = false )   private  String  address;   private  String  pin; }
 
需要注意的通过 builder.excludeFieldsWithoutExposeAnnotation()方法是该注解生效。
1 2 3 4 final  GsonBuilder builder = new  GsonBuilder();   builder.excludeFieldsWithoutExposeAnnotation();   final  Gson gson = builder.create();
 
3 @Since和@Until注解 Since代表“自从”,Until 代表”一直到”。它们都是针对该字段生效的版本。比如说 @Since(1.2)代表从版本1.2之后才生效,@Until(0.9)代表着在0.9版本之前都是生效的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public  class  SoccerPlayer  {   private  String name;   @Since(1.2)    private  int shirtNumber;   @Until(0.9)    private  String country;   private  String teamName;    }
 
也就是说我们利用方法builder.setVersion(1.0)定义版本1.0,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 final  GsonBuilder builder = new  GsonBuilder();    builder.setVersion(1.0 );    final  Gson gson = builder.create();    final  SoccerPlayer account = new  SoccerPlayer();    account.setName("Albert Attard" );    account.setShirtNumber(10 );     account.setTeamName("Zejtun Corinthians" );    account.setCountry("Malta" );     final  String  json = gson.toJson(account);    System.out.printf("Serialised (version 1.0)%n  %s%n" , json);
 
由于shirtNumber和country作用版本分别是1.2之后,和0.9之前,所以在这里都不会得到序列化,所以输出结果是:
1 2 3 Serialised (version 1.0)   {"name" :"Albert Attard" ,"teamName" :"Zejtun Corinthians" }
 
 
Gson 序列化 英文Serialize和format都对应序列化,这是一个Java对象到JSON字符串的过程。 接着看一个例子,下面分别是java类和以及我们期望的JSON数据:
1 2 3 4 5 6 7 8 9 public  class  Book  {   private  String [] authors;   private  String  isbn10;   private  String  isbn13;   private  String  title;    }
 
1 2 3 4 5 6 7 8 9 10 {    "title" :  "Java Puzzlers: Traps, Pitfalls, and Corner Cases" ,    "isbn-10" :  "032133678X" ,    "isbn-13" :  "978-0321336781" ,    "authors" :  [      "Joshua Bloch" ,      "Neal Gafter"    ] } 
 
你肯定能发现JSON数据中出现了isbn-10和isbn-13, 我们怎么把字段数据isbn10和isbn13转化为JSON数据需要的isbn-10和isbn-13,Gson当然为我们提供了对应的解决方案
1 序列化方案1 采用上面提到的@SerializedName注解。
1 2 3 4 5 6 7 8 9 10 11 12 13 public  class  Book  {   private  String [] authors;   @SerializedName ("isbn-10" )   private  String  isbn10;   @SerializedName ("isbn-13" )   private  String  isbn13;   private  String  title;    }
 
2 序列化方案2 利用JsonSerializer类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  class  BookSerialiser  implements  JsonSerializer  {     @Override      public  JsonElement serialize (final  Book book, final  Type typeOfSrc, final  JsonSerializationContext context)  {         final  JsonObject  jsonObject  =  new  JsonObject ();         jsonObject.addProperty("title" , book.getTitle());         jsonObject.addProperty("isbn-10" , book.getIsbn10());         jsonObject.addProperty("isbn-13" , book.getIsbn13());         final  JsonArray  jsonAuthorsArray  =  new  JsonArray ();         for  (final  String author : book.getAuthors()) {             final  JsonPrimitive  jsonAuthor  =  new  JsonPrimitive (author);             jsonAuthorsArray.add(jsonAuthor);         }         jsonObject.add("authors" , jsonAuthorsArray);         return  jsonObject;     } }
 
下面对序列化过程进行大致的分析:
JsonSerializer是一个接口,我们需要提供自己的实现,来满足自己的序列化要求。 
 
1 2 3 4 5 6 7 8 9 10 11 public  interface  JsonSerializer <T> {      public  JsonElement serialize (T src, Type typeOfSrc, JsonSerializationContext context) ; }
 
首先在上面的代码中,我们需要创建的是一个JsonElement对象,这里对应Book是一个对象,所以创建一个JsonObject类型。final JsonObject jsonObject = new JsonObject(); 
然后我们将相应字段里面的数据填充到jsonObject里面。 
 
1 2 3 jsonObject.addProperty ... jsonObject.add ...
 
下面是jsonObject中的添加方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16      final  GsonBuilder  gsonBuilder  =  new  GsonBuilder ();     gsonBuilder.registerTypeAdapter(Book.class, new  BookSerialiser ());     gsonBuilder.setPrettyPrinting();     final  Gson  gson  =  gsonBuilder.create();     final  Book  javaPuzzlers  =  new  Book ();     javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases" );     javaPuzzlers.setIsbn10("032133678X" );     javaPuzzlers.setIsbn13("978-0321336781" );     javaPuzzlers.setAuthors(new  String [] { "Joshua Bloch" , "Neal Gafter"  });          final  String  json  =  gson.toJson(javaPuzzlers);     System.out.println(json);
 
,这里对应的是gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser())方法进行JsonSerializer的配置。在上面例子中,通过调用gsonBuilder.setPrettyPrinting();方法还告诉了 Gson 对生成的 JSON 对象进行格式化
 
Gson 反序列化 英文parse和deserialise对应反序列化,这是一个字符串转换成Java对象的过程。 我们同样采用上面一小节的代码片段,只不过现在我们需要做的是将:
1 2 3 4 5 6 7 8 9 10 {    "title" :  "Java Puzzlers: Traps, Pitfalls, and Corner Cases" ,    "isbn-10" :  "032133678X" ,    "isbn-13" :  "978-0321336781" ,    "authors" :  [      "Joshua Bloch" ,      "Neal Gafter"    ] } 
 
转化为对应的Book实体类,
1 反序列化方案1 利用@SerializedName 注解 也就是说我们的实体类Book.java可以这么写:
1 2 3 4 5 6 7 8 9 10 11 12 13 public  class  Book  {   private  String [] authors;   @SerializedName ("isbn-10" )   private  String  isbn10;   @SerializedName (value = "isbn-13" , alternate = {"isbn13" ,"isbn.13" })   private  String  isbn13;   private  String  title;    }
 
可以看到这里我们在@SerializedName 注解使用了一个value, alternate字段,value也就是默认的字段,对序列化和反序列化都有效,alternate只有反序列化才有效果。也就是说一般服务器返回给我们JSON数据的时候可能同样的一个图片,表示”image”,”img”,”icon”等,我们利用@SerializedName 中的alternate字段就能解决这个问题,全部转化为我们实体类中的图片字段。
 
2 反序列化方案2 我们在序列化的时候使用的是JsonSerialize ,这里对应使用JsonDeserializer 我们将解析到的json数据传递给Book的setter方法即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class  BookDeserializer  implements  JsonDeserializer <Book >  {   @Override    public Book deserialize(final  JsonElement json, final  Type  typeOfT, final  JsonDeserializationContext context)       throws JsonParseException {     final  JsonObject jsonObject = json.getAsJsonObject();     final  JsonElement jsonTitle = jsonObject.get ("title" );     final  String  title = jsonTitle.getAsString();     final  String  isbn10 = jsonObject.get ("isbn-10" ).getAsString();     final  String  isbn13 = jsonObject.get ("isbn-13" ).getAsString();     final  JsonArray jsonAuthorsArray = jsonObject.get ("authors" ).getAsJsonArray();     final  String [] authors = new  String [jsonAuthorsArray.size()];     for  (int  i = 0 ; i < authors.length; i++) {       final  JsonElement jsonAuthor = jsonAuthorsArray.get (i);       authors[i] = jsonAuthor.getAsString();     }     final  Book book = new  Book();     book.setTitle(title);     book.setIsbn10(isbn10);     book.setIsbn13(isbn13);     book.setAuthors(authors);     return  book;   } }
 
和Gson序列化章节一样,我们这里接着分析我们是怎么将JSON数据解析(反序列化)为实体类的:
因为我们可以发现上面的JSON数据是一个{}大括号包围的,也就意味着这是一个Json对象。所以首先我们通过final JsonObject jsonObject = json.getAsJsonObject();将我们的JsonElement转化为JsonObject 
通过jsonObject.get("xxx").getAsString()的形式获取相应String的值 
通过jsonObject.get("xx").getAsJsonArray();获取相应的json数组,并遍历出其中的相应字段值 
通过setter方法,将获取到的值设置给Book类。 
最终返回的是 Book的对象实例。完成了JSON->javaBean的转化 
同样需要配置 
关于从本地流中读取Json数据可以使用 InputStreamReader完成 
 
1 2 3 4 5 6 7 8 9 10 11 12     GsonBuilder gsonBuilder = new GsonBuilder();    gsonBuilder.registerTypeAdapter(Book.class , new BookDeserializer());    Gson gson = gsonBuilder.create();        try (Reader reader = new InputStreamReader(Main.class .getResourceAsStream("/part1/sample.json" ), "UTF-8" )){            Book book = gson.fromJson(reader, Book.class );      System.out .println(book);    }
 
泛类型反序列化方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 import  com.google.common.reflect.TypeToken;import  com.google.gson.Gson;import  com.google.gson.JsonSyntaxException;import  java.lang.reflect.Type;public  class  JsonHelper  {     public  static  void  main (String[] args)  {         String  respStr  =  "{\"status\":0,\"msg\":\"\",\"data\":{\"cardNo\":\"12345677\"}}" ;         BaseResponse<CardInfo> cardInfo = parseResponse(respStr);         System.out.println(cardInfo.data);         respStr = "{\"status\":0,\"msg\":\"\",\"data\":{\"id\":\"123445678\",\"name\":\"张三\"}}" ;         BaseResponse<UserInfo> userInfo = parseResponse(respStr);         System.out.println(userInfo.data);     }     private  static  <T> BaseResponse<T> parseResponse (String responseData)  throws  JsonSyntaxException {         Gson  gson  =  new  Gson ();         Type  jsonType  =  new  TypeToken <BaseResponse<T>>() {         }.getType();         BaseResponse<T> result = gson.fromJson(responseData, jsonType);         return  result;     }     class  BaseResponse <T> {         private  int  status;         public  int  getStatus ()  {             return  status;         }         public  void  setStatus (int  status)  {             this .status = status;         }         public  String getMsg ()  {             return  msg;         }         public  void  setMsg (String msg)  {             this .msg = msg;         }         public  T getData ()  {             return  data;         }         public  void  setData (T data)  {             this .data = data;         }         private  String msg;         private  T data;     }     class  UserInfo  {         private  String name;         public  String getName ()  {             return  name;         }         public  void  setName (String name)  {             this .name = name;         }         @Override          public  String toString ()  {             return  "UserInfo{"  +                     "name='"  + name + '\''  +                     ", Id='"  + Id + '\''  +                     '}' ;         }         public  String getId ()  {             return  Id;         }         public  void  setId (String id)  {             Id = id;         }         private  String Id;     }     class  CardInfo  {         public  String getCardNo ()  {             return  cardNo;         }         public  void  setCardNo (String cardNo)  {             this .cardNo = cardNo;         }         @Override          public  String toString ()  {             return  "CardInfo{"  +                     "cardNo='"  + cardNo + '\''  +                     '}' ;         }         private  String cardNo;     } }