GSON- GSON
GSON是Google的JSON解析器和Java生成器。 Google开发了GSON供内部使用,但后来将其开源。 GSON相当容易使用,但我认为它不如Hyman逊或者布恩(我认为获胜者)优雅。在本GSON教程中,我将指导我们如何使用GSON将JSON解析为Java对象,以及将Java对象序列化为JSON。
GSON包含多个可用于JSON的API。本教程介绍了" Gson"组件,该组件将JSON解析为Java对象,或者从Java对象生成JSON。除了Gson
组件外,GSON在GSON JsonReader组件中还具有拉式解析器。
在使用GSON之前,必须首先在Java项目中安装GSON。我已经在有关GSON Installation的文章中对此进行了解释。
创建一个Gson实例
在使用GSON之前,必须首先创建一个新的Gson
对象。有两种创建" Gson"实例的方法:
- 使用
new Gson()
- 创建一个GsonBuilder实例并在其上调用create()。
这两种创建Gson实例的方式都将在本GSON教程中介绍。
新Gson()
我们可以简单地通过使用new Gson()指令创建对象来创建Gson对象。这是创建Gson
对象的样子:
Gson gson = new Gson();
一旦创建了Gson
实例,我们就可以开始使用它来解析和生成JSON。
GsonBuilder.build()
创建Gson实例的另一种方法是创建GsonBuilder()并调用其create()方法。这是创建GsonBuilder
并调用create()
的示例:
GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create();
使用GsonBuilder
允许我们在创建Gson
对象之前在GsonBuilder
上设置配置选项。我们将在本GSON教程的后面看到有关此示例。
将JSON解析为Java对象
GSON可以使用Gson对象的fromJson()方法将JSON插入Java对象。这是将JSON解析为Java对象的GSON示例:
String json = "{\"brand\":\"Jeep\", \"doors\": 3}"; Gson gson = new Gson(); Car car = gson.fromJson(json, Car.class);
该示例的第一行定义了要解析的JSON字符串。第二行创建一个" Gson"实例。第三行调用gson.fromJson()方法,该方法将JSON字符串解析为Car对象。
fromJson()的第一个参数是JSON来源。在上面的示例中,JSON源是一个字符串。 fromJson()方法的第二个参数是用于解析JSON到其实例的Java类。 " Gson"实例创建该类的实例,并将JSON解析为该类。因此,我们应确保此类具有无参数构造函数,否则GSON无法使用它。
这是Car
类的外观:
public class Car { public String brand = null; public int doors = 0; }
从Java对象生成JSON
GSON还可以从Java对象生成JSON。我们可以通过" Gson"对象来实现。要生成JSON,我们可以调用Gson对象的toJson()方法。这是一个使用GSON从Java对象生成JSON的示例:
Car car = new Car(); car.brand = "Rover"; car.doors = 5; Gson gson = new Gson(); String json = gson.toJson(car);
漂亮的印刷
默认情况下,由new Gson()
创建的Gson
实例以尽可能紧凑的JSON打印(生成)。这是默认Gson
实例的紧凑型JSON输出示例:
{"brand":"Rover","doors":5}
但是,这种紧凑的JSON可能很难阅读。因此,GSON提供了一个漂亮的打印选项,可以其中打印JSON,以便在文本编辑器中更容易阅读。这是一个如何在启用漂亮打印的情况下创建Gson
实例的示例:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
这是打印相同的JSON的示例:
{ "brand": "Rover", "doors": 5 }
排除字段
我们可以告诉GSON从序列中排除Java类中的字段。有几种告诉GSON排除字段的方法。 GSON教程的以下部分将介绍最有用和最容易使用的排除字段的方法。
临时字段
如果我们在Java类" transient"中创建一个字段,那么GSON将在序列化和反序列化中均将其忽略。这是前面的"汽车"类的外观,其中"品牌"字段标记为"Transient":
public class Car { public transient String brand = null; public int doors = 0; }
@Expose批注
GSON@ Expose
批注(com.google.gson.annotations.Expose
)可用于在对象序列化或者反序列化时将要公开或者不公开(包含或者不包含)的字段标记为。 @Expose注释可以带有两个参数。每个参数都是一个布尔值,可以取值true或者false。这是一些GSON@ Expose
注释示例,以显示我的意思:
@Expose(serialize = true); @Expose(serialize = false); @Expose(deserialize = true); @Expose(deserialize = false); @Expose(serialize = true , deserialize = false); @Expose(serialize = false, deserialize = true);
@Expose
批注的serialize参数指定在序列化拥有对象时是否应包含带有@Expose批注的字段。 " deserialize"参数指定在对拥有的对象进行反序列化时是否应读取该字段。
这是一个使用GSON@ Expose
注释的示例类:
public class Car { @Expose(serialize = false, deserialize = false) public String brand = null; @Expose(serialize = true, deserialize = true) public int doors = 0; }
注意字段上方的@Expose批注,告诉我们序列化或者反序列化时是否应包含给定的字段。
为了使GSON对@Expose批注做出反应,我们必须使用GsonBuilder类创建一个Gson实例。看起来是这样的:
GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); Gson gson = builder.create();
注意,这种配置使GSON忽略了所有没有@ Expose
注释的字段。要在序列化或者反序列化中包含一个字段,它上面必须有一个@Expose批注。
GsonBuilder.setExclusionStrategies()
在GSON中从序列化或者反序列化中排除类字段的另一种方法是在GsonBuilder
上设置ExclusionStrategy
,并使用GsonBuilder
来构建Gson
对象。
ExclusionStrategy是一个接口,因此我们必须创建一个实现ExclusionStrategy接口的类。这是一个使用匿名类实现ExclusionStrategy
接口的示例:
ExclusionStrategy exclusionStrategy = new ExclusionStrategy() { public boolean shouldSkipField(FieldAttributes fieldAttributes) { if("brand".equals(fieldAttributes.getName())){ return true; } return false; } public boolean shouldSkipClass(Class<?> aClass) { return false; } };
注意,在示例ExclusionStrategy实现的shouldSkipField()方法内部,该示例检查给定的字段名称是否为brand。如果是,则将该字段排除在序列化和反序列化之外。
要使用ExclusionStrategy实现,请创建一个GsonBuilder,并使用setExclusionStrategies()方法在其上设置ExclusionStrategy,如下所示:
GsonBuilder builder = new GsonBuilder(); builder.setExclusionStrategies(exclusionStrategy); Gson gson = builder.create();
" exclusionStrategy"变量必须指向" ExclusionStrategy"接口的实现。
序列化空字段
默认情况下," Gson"对象不会将具有" null"值的字段序列化为JSON。如果Java对象中的字段为null,则Gson会将其排除。
我们可以通过GsonBuilder强制Gson序列化null值。这是一个示例,显示了如何使用GSON强制对null值进行序列化:
GsonBuilder builder = new GsonBuilder(); builder.serializeNulls(); Gson gson = builder.create(); Car car = new Car(); car.brand = null; String json = gson.toJson(car); System.out.println(json);
请注意,在创建Gson
对象之前,先在GsonBuilder
实例上调用serializeNulls()
。一旦调用了" serializeNulls()",则由" GsonBuilder"创建的" Gson"实例将在序列化的JSON中包含" null"字段。
上面示例的输出为:
{"brand":null,"doors":0}
注意" brand"字段如何为空。
GSON中的自定义实例创建者
默认情况下,GSON将尝试通过调用该类的no-arg构造函数来创建该类的实例。但是,如果给定的类没有默认的构造函数,或者我们想要对实例进行一些默认配置,或者想要创建子类的实例,则需要创建并注册自己的实例创建者。
GSON实例创建者只是一个对象工厂。实例创建者必须实现InstanceCreator
接口(com.google.gson.InstanceCreator
)。这是一个InstanceCreator
实现的例子:
import com.google.gson.InstanceCreator; public class CarCreator implements InstanceCreator<Car> { public Car createInstance(Type type) { Car car = new Car(); car.brand = "Toyota"; return car; } }
在创建Gson实例之前,可以通过在GsonBuilder上注册上述CarCreator类来使用它。这是一个例子:
GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Car.class, new CarCreator()); Gson gson = gsonBuilder.create();
现在," Gson"实例将使用" CarCreator"实例创建" Car"实例。我们可以通过运行以下代码(在注册" CarCreator"之后)向自己证明:
String carJson = "{ \"doors\" : 4 }"; Car car = gson.fromJson(carJson, Car.class); System.out.println(car.brand);
默认的brand属性值为null,并且JSON字符串不包含brand属性。因此,我们将看到在CarCreator的createInstance()方法(Toyota)内设置的brand属性的值。
GSON中的版本支持
GSON包含对其读取和写入的Java对象的简单版本支持。 GSON版本支持意味着我们可以用版本号标记Java类中的字段,然后让GSON根据它们的版本号在Java类中包括或者排除字段。
要使用GSON版本支持,我们必须首先使用GSON@ Since
注释对Java类进行注释。这是一个示例" Person"类,其字段带有" @Since"注释:
import com.google.gson.annotations.Since; public class Person { @Since(1.0) public String firstName = null; @Since(1.0) public String lastName = null; @Since(2.0) public String middleName = null; @Since(3.0) public String email = null; }
其次,我们必须创建一个GsonBuilder
并告诉它应该序列化到哪个版本以及从中反序列化。这是一个如何创建GsonBuilder
并在其上设置版本号的示例:
GsonBuilder builder = new GsonBuilder(); builder.setVersion(2.0); Gson gson = builder.create();
由上述GsonBuilder创建的Gson实例现在将仅包含以@Since(2.0)或者低于2.0的版本号注释的字段。在上面的"人"示例类中,这意味着字段"名字","姓氏"和"中间名"。 " email"字段使用版本3.0进行了注释,该版本高于2.0,因此GSON将排除" email"字段。
这是将" Person"对象序列化为JSON并查看生成的JSON的示例:
Person person = new Person(); person.firstName = "John"; person.lastName = "Doe"; person.middleName = "Blocks"; person.email = "[email protected]"; GsonBuilder builder = new GsonBuilder(); builder.setVersion(2.0); Gson gson = builder.create(); String personJson = gson.toJson(person); System.out.println(personJson);
本示例将打印出以下JSON字符串:
{"firstName":"John","lastName":"Doe","middleName":"Blocks"}
请注意,GSON如何在生成的JSON中排除email
字段。
排除基于版本的字段对于将JSON读入Java对象(反序列化)的工作原理相同。查看下面的JSON字符串,其中包含所有字段,包括email
字段:
"{\"firstName\":\"John\",\"lastName\":\"Doe\",\"middleName\":\"Blocks\",\"email\":\"[email protected]\"}"
如果我们要使用上面的Gson
对象来读取Person
对象,那么即使JSON字符串中存在email
字段也不会被读取。这是使用上述Gson
实例读取Person
对象的样子:
String personJson2 = "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"middleName\":\"Blocks\",\"email\":\"[email protected]\"}"; Person personRead = gson.fromJson(personJson2, Person.class);
自定义序列化和反序列化
GSON为我们提供了插入客户串行器和解串器的可能性。自定义序列化程序可以将Java值转换为自定义JSON,而自定义反序列化程序可以再次将自定义JSON转换为Java值。
自定义序列化器
GSON中的自定义序列化程序必须实现JsonSerializer
接口。 JsonSerializer界面如下所示:
public interface JsonSerializer<T> { public JsonElement serialize(T value, Type type, JsonSerializationContext jsonSerializationContext) { } }
实现一个可以序列化布尔值的自定义序列化器,如下所示:
public class BooleanSerializer implements JsonSerializer<Boolean> { public JsonElement serialize(Boolean aBoolean, Type type, JsonSerializationContext jsonSerializationContext) { if(aBoolean){ return new JsonPrimitive(1); } return new JsonPrimitive(0); } }
注意如何在两个地方用Boolean类替换T型参数。
在" serialize()"方法内部,我们可以将值(此cas中的" Boolean")转换为需要" serialize()"方法返回的" JsonElement"。在上面的示例中,我们使用了一个JsonPrimitive,它也是一个JsonElement。如我们所见,布尔值" true"被转换为1,而" false"被转换为0,而不是JSON中通常使用的" true"和" false"。
注册此自定义序列化器的操作如下:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Boolean.class, new BooleanSerializer()) ; Gson gson = builder.create();
这是对" registerTypeAdapter()"的调用,它向GSON注册了客户序列化程序。
一旦注册,从GsonBuilder创建的Gson实例将使用自定义序列化器。为了了解其工作原理,我们将使用以下POJO类:
public class PojoWithBoolean { public String username = null; public Boolean isSuperUser = false; }
这是序列化PojoWithBoolean
实例的样子:
PojoWithBoolean pojo = new PojoWithBoolean(); pojo.username = "abc"; pojo.isSuperUser = false; String pojoJson = gson.toJson(pojo); System.out.println(pojoJson);
从此示例打印的输出将是:
{"username":"abc","isSuperUser":0}
注意,isSuperUser的false值如何转换为0。
自定义反序列化器
GSON还为自定义解串器提供支持。自定义解串器必须实现JsonDeserializer接口。 JsonDeserializer界面如下所示:
public interface JsonDeserializer<T> { public Boolean deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException; }
为Boolean类型实现自定义反序列化器如下所示:
public class BooleanDeserializer implements JsonDeserializer<Boolean> { public Boolean deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { return jsonElement.getAsInt() == 0 ? false : true; } }
使用另一个版本的registerTypeConverter()方法向GSON注册自定义解串器。这是向GSON注册上述解串器的样子:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Boolean.class, new BooleanDeserializer()); Gson gson = builder.create();
这是使用创建的Gson
实例解析JSON字符串的样子:
String jsonSource = "{\"username\":\"abc\",\"isSuperUser\":1}"; PojoWithBoolean pojo = gson.fromJson(jsonSource, PojoWithBoolean.class); System.out.println(pojo.isSuperUser);
从此GSON定制反序列化器示例打印的输出为:
true
...,因为JSON字符串中的1将转换为布尔值true
。