Gson
  目前主流的json解析类库有jackson,fastjson,gson,gson的serialization deserialization解析功能无疑是最强大的,基本上完美支持复杂对象的json化和反json化,其他两个库在转换复杂对象时都容易出现问题。如果在不考虑效率的情况下,我强烈推荐使用gson类库。
  首先需要添加依赖
  //gradle  dependencies {     compile 'com.google.code.gson:gson:2.8.2' }  //maven <dependencies>     <!--  Gson: Java to Json conversion -->     <dependency>       <groupId>com.google.code.gson</groupId>       <artifactId>gson</artifactId>       <version>2.8.2</version>       <scope>compile</scope>     </dependency> </dependencies>
  接下来看一些代码例子,gson设计的非常易用,基本上一看就懂。
    
   转换基础数据类型
  // 创建gson对象,gson对象是内部无状态的,所以创建一个可以多次使用,可以想象成一个转换器 Gson gson = new Gson(); //转换成json只用直接放入对象就行,gson在内部会提取对象的类型信息 gson.toJson(1);            // ==> 1 gson.toJson("abcd");       // ==> "abcd" gson.toJson(new Long(10)); // ==> 10 int[] values = { 1 }; gson.toJson(values);       // ==> [1]  // 反json化,此时需要传入类型参数,因为json中是没有保存关于java类型的信息的 int one = gson.fromJson("1", int.class); Integer one = gson.fromJson("1", Integer.class); Long one = gson.fromJson("1", Long.class); String str = gson.fromJson("\"abc\"", String.class);
    
   转换对象类型
  当然,gson也支持对对象类型的转换
  class BagOfPrimitives {   private int value1 = 1;   private String value2 = "abc";   //使用transient标识的变量不会被json化    private transient int value3 = 3;   BagOfPrimitives() {     // no-args constructor   } }  // Serialization BagOfPrimitives obj = new BagOfPrimitives(); Gson gson = new Gson(); String json = gson.toJson(obj);    // ==> json is {"value1":1,"value2":"abc"}
  不过注意你不能json化一个具有循环引用的对象,会导致死循环(简单来说就是a有一个变量为b,b也有一个变量为a,此时无论json化谁都会导致死循环)
    
   使用gson序列化对象的要点
  1.完全可以使用private修饰变量类型,因为gson内部是使用反射来进行json化的,所以private也完全可以读取的到 
 2.完全没有必要使用任何的annotations 来标注哪个字段需要被包含(有很多其他库是使用annotations 来标记的),gson默认会序列化当前类中的所有字段(包括他的所有父类) 
 3.如果一个字段被标记为transient,他不会被Json化 
 4.gson对值为null的字段有很好的支持
    
   转换数组类型
  Gson gson = new Gson(); int[] ints = {1, 2, 3, 4, 5}; String[] strings = {"abc", "def", "ghi"};  // Serialization gson.toJson(ints);     // ==> [1,2,3,4,5] gson.toJson(strings);  // ==> ["abc", "def", "ghi"]  // Deserialization int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class); 
    
   集合类型
  java对集合类型是做了特殊支持的,输出的效果基本和数组一样,除了元素之外不会输出其他的字段例如 size之类的
          Gson gson = new Gson();         Collection<Integer> ints = Arrays.asList(1,2,3,4,5);          // Serialization         String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]          // Deserialization         //对于泛型类型,因为直接取得的class并不包括泛型类型,所以需要创建type再传入         Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();         Collection<Integer> ints2 = gson.fromJson(json, collectionType);
    
   转换泛型类型
  因为gson内部是使用getClass来获取类型信息,返回的类型都不包括泛型参数类型,所以直接像之前使用的话,序列化和反序列化都会失败 
 (其实不只是gson,java的泛型本身就被吐槽很久了,各种毛病)
  class Foo<T> {   T value; } Gson gson = new Gson(); Foo<Bar> foo = new Foo<Bar>(); gson.toJson(foo); //不能成功序列化  gson.fromJson(json, foo.getClass()); // 无法反序列化
  如果想要成功序列化带有泛型类型的对象,需要使用Type对象
  //注意这里的TypeToken带有{},其实是一个匿名类,因为TypeToken的构造器是非Public的,不能直接构造,我也不太清楚为什么要这样设计 Type fooType = new TypeToken<Foo<Bar>>() {}.getType(); gson.toJson(foo, fooType);  gson.fromJson(json, fooType);
    
   转换带有混合类型的集合
  有时候你可能会在一个集合中放入不同的类型(虽然我个人强烈不推荐这样写,因为泛型的作用就是为了省掉不必要的cast,你还放入不同类型,这不是自找麻烦吗?) 
 但是如果你真的这样写了,gson还是可以帮你转换
  Collection collection = new ArrayList(); collection.add("hello"); collection.add(5); collection.add(new Event("GREETINGS", "guest"));  class Event {   private String name;   private String source;   private Event(String name, String source) {     this.name = name;     this.source = source;   } }
  你完全可以像直接一样直接序列化这个集合,没有任何问题。 
 但是之前也说过,json没有保存关于java对象类型的任何信息(作为一个通用的数据交换格式他这样做是正确的,否则这段json数据就只有gson才能解析了)。 
 之前我们在反序列化的同时都要手动传入类型参数,但是作为一个混合集合,显然没有一个所谓的’类型参数’,所以直接反序列化是不可能了。 
 如果你想要反序列化这样的json,有以下几种选择。 
 1.使用原始的json类库手动解析 
 2.注册一个collection 的adapter(我们下一篇会讲),自定义解析过程(还是需要手动解析) 
 所以如果想要反序列化这样的集合,无论怎么样都要手写解析,没什么办法,所以最好还是不要在泛型集合里放入不同的类型
   
  除了默认的序列化和反序列化行为,gson还允许自定义某些类的序列化和反序列化行为。自定义行为一般用于需要使json对象具有和原来类不同的表示形式,或者默认行为会报错的情况。主要分为三个类 
 Json Serializers: 自定义某种对象类型的序列化行为
  Json Deserializers: 自定义某种对象类型的反序列化行为
  Instance Creators: 自定义某种对象的创建行为
  此时我们需要配置gsonbuilder,然后用gsonbuilder来创建gson对象,builder模式大家应该很熟悉了 
 代码如下
  GsonBuilder gsonBuilder= new GsonBuilder(); gson.registerTypeAdapter(MyType.class, new MySerializer()); gson.registerTypeAdapter(MyType.class, new MyDeserializer()); gson.registerTypeAdapter(MyType.class, new MyInstanceCreator()); Gson gson=gsonBuilder.create();
  为某类型注册了自定义的序列化和反序列化行为之后,在转换的过程中一旦遇到该类型的对象,就会调用你注册的行为来序列化。 
 这些的类的实现也很容易。
  //自定义序列化,需要实现JsonSerializer接口 private class DateTimeSerializer implements JsonSerializer<DateTime> {   public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {     return new JsonPrimitive(src.toString());   } } //自定义序列化,需要实现DateTimeDeserializer 接口 private class DateTimeDeserializer implements JsonDeserializer<DateTime> {   public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)       throws JsonParseException {     return new DateTime(json.getAsJsonPrimitive().getAsString());   } } //自定义对象创建,需要实现InstanceCreator private class MoneyInstanceCreator implements InstanceCreator<Money> {   public Money createInstance(Type type) {     return new Money("1000000", CurrencyCode.USD);   } } 
  在我个人使用gson的过程中,我发现有些时候是不得不用自定义序列化和反序列化的,因为在使用默认的行为的情况下,对一些复杂对象经常出错,具体原因我也不知道为什么,很多时候都是出现了死循环,可能java一些类中本身就存在双向引用吧,此外还有一些其他的异常,主要原因都是java一些类本身的继承结构太深了。
   
  我们以序列化Image为例(该类直接序列化会报错) 
 这个代码是我实际项目中使用的,将javafx的image对象序列化(当然对于图像对象,最后还要使用压缩流来减少体积)
  public class GsonImage implements JsonSerializer<Image>,JsonDeserializer<Image> {      @Override     public Image deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)             throws JsonParseException {          Gson gson=new Gson();         byte[] bs=gson.fromJson(json.getAsString(), byte[].class);         BufferedImage image = null;         try {             //从字节数组创建图片             image = ImageIO.read(new ByteArrayInputStream(bs));         } catch (IOException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }         Image image2=SwingFXUtils.toFXImage(image, null);          return image2;     }      @Override     public JsonElement serialize(Image image, Type typeOfSrc, JsonSerializationContext context) {            Gson gson=new Gson();         ByteArrayOutputStream stream=new ByteArrayOutputStream();         BufferedImage bufferedImage=SwingFXUtils.fromFXImage(image, null);         try {             ImageIO.write(bufferedImage, "PNG", stream);         } catch (IOException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }         byte[] imgBytes=stream.toByteArray();         //实际上序列化的是字节数组         String string=gson.toJson(imgBytes);          return new JsonPrimitive(string);     }  }
  除了三种自定义行为之外,gsonbuilder还提供了一些配置
  setPrettyPrinting() //设置输出格式为可读性优先(默认是体积小优先) serializeNulls() //设置输出null(默认null会被忽略) excludeFieldsWithModifiers()//设置不被包括在序列化中的修饰符(默认为static //transient,但是你可以覆盖设置)
  关于gson就介绍到这里
  可以访问gson的github帮助页面来获取更多信息 
 https://github.com/google/gson/blob/master/UserGuide.md