网站建设设,汨罗做网站,定制开发app,域名 wordpress文章目录一、简介二、依赖三、基本用法1、创建Gson实例1.1、new Gson()1.2、GsonBuilder.build()2、Java对象–JSON3、JSON–Java对象4、漂亮地输出5、JSON array -- Java array/list5.1 、 JSON array --Java对象5.2 、JSON array–List5.3 、JSON array–…
文章目录一、简介二、依赖三、基本用法1、创建Gson实例1.1、new Gson()1.2、GsonBuilder.build()2、Java对象–JSON3、JSON–Java对象4、漂亮地输出5、JSON array -- Java array/list5.1 、 JSON array --Java对象5.2 、JSON array–List5.3 、JSON array–成员变量5.3.1、数组类型成员变量5.3.2、List类型成员变量6、JSON ----Set6.1、Set–JSON6.2、JSON–Set7、Null值处理7.1、如何在序列化时允许空值8、版本支持8.1、Since注解8.2、如何使用Since注解编写版本化的类8.3、创建具备版本支持的Gson实例8.4、实例8.4.1、 具备版本支持的序列化8.4.2、具备版本支持的反序列化9、更改Java对象和JSON的字段名映射9.1、SerializedName9.2、序列化期时更改字段名称9.3、反序列化时更改字段名称10、排除或忽略字段10.1、Expose注解10.1.1. 怎么用 Expose10.1.2、创建Gson实例10.2、用修饰符排除字段10.2.1、transient 字段10.2.2、其他修饰符10.3、排除策略四、GsonBuilder1、GsonBuilder.setPrettyPrinting()–漂亮地打印JSON2、FieldNamingPolicy2.1、FieldNamingPolicy.IDENTITY2.2、FieldNamingPolicy.LOWER_CASE_WITH_DASHES2.3、FieldNamingPolicy.LOWER_CASE_WITH_DOTS2.4、FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES2.5、 FieldNamingPolicy.UPPER_CAMEL_CASE2.6、FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES3、GsonBuilder.serializeNulls()——空值的序列化4、GsonBuilder.setExclusionStrategies()5、GsonBuilder.setLenient()——宽松的JSON语法规则五、JsonReader1、JsonReader2、Tokens3、如何创建GSON JsonReader4、读取JSON流六、JsonParser1、创建JsonParser2、转化JSON3、 JsonElement, JsonObject 和JsonArray4、Gson JsonParser 示例5、使用fromJson() 获取JsonObject6、迭代JSON树结构七、自定义序列化和反序列化1、自定义序列化1.1、JsonSerializer接口1.2、自定义序列化示例2、自定义反序列化2.1、JsonDeserializer接口2.2、自定义反序列化示例一、简介
Gson又称Google Gson是Google公司发布的一个开放源代码的Java库主要用途为序列化Java对象为JSON字符串或反序列化JSON字符串成Java对象。
Gson官网 gson
Gson源码地址 google/gson
二、依赖
使用Maven导入依赖 dependencygroupIdcom.google.code.gson/groupIdartifactIdgson/artifactIdversion2.8.5/version/dependencyGradle导入依赖
compile group: com.google.code.gson, name: gson, version: 2.8.51.三、基本用法
1、创建Gson实例
使用Gson的第一步是创建一个Gson对象创建爱你Gson对象有两种方式
使用 new Gson()创建GsonBuilder实例使用 create() 方法
1.1、new Gson()
示例如下
Gson gson new Gson();1.2、GsonBuilder.build()
示例如下
GsonBuilder builder new GsonBuilder();
Gson gson builder.create();2、Java对象–JSON
下面会用到这个实体类
public class Employee {private int id;private String firstName;private String lastName;private String email;//省略getter/setter构造方法toSting方法
}在Gson中的序列化即将Java对象转换为其JSON表示形式。 为了进行序列化首先需要一个Gson对象该对象可以处理转换。 接下来需要调用函数toJson()方法并传入Employee对象。
Employee emp new Employee(1001, Lokesh, Gupta, howtodoinjavagmail.com);Gson gson new Gson();String jsonString gson.toJson(emp);System.out.println(jsonString);运行结果 3、JSON–Java对象
在Gson进行反序列指的是将JSON字符串转换为Java对象。 为了进行反序列化我们需要使用Gson对象调用fromJson()函数并在解析完成后传递两个参数即JSON字符串和所需的Java类型。
String jsonString {id:1001, firstName:Lokesh, lastName:Gupta, email:howtodoinjavagmail.com};Gson gson new Gson();Employee empObject gson.fromJson(jsonString, Employee.class);System.out.println(empObject);运行结果 4、漂亮地输出
默认情况下Gson以紧凑格式打印JSON即字段名称及其值对象字段以及JSON输出中数组内的对象等之间将没有空格。
登录后复制
{id:1,firstName:Lokesh,lastName:Gupta, emailId:howtogoinjavagmail.com}但是这种紧凑的JSON可能很难阅读。因此GSON提供了一个漂亮的打印选项可以在其中打印JSON以便于更加方便阅读。
Gson gson new GsonBuilder().setPrettyPrinting().create();Employee employeeObj new Employee(1, Lokesh, Gupta, howtogoinjavagmail.com);System.out.println(gson.toJson(employeeObj));运行结果 5、JSON array -- Java array/list
5.1 、 JSON array --Java对象
users.json
[{name: Alex,id: 1},{name: Brian,id: 2},{name: Charles,id: 3}
]User.java
public class User
{private long id;private String name;public long getId() {return id;}public void setId(long id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}Overridepublic String toString() {return User [id id , name name ];}
}将json数组反序列化为Java对象数组
String userJson [{name: Alex,id: 1}, {name: Brian,id:2}, {name: Charles,id: 3}];Gson gson new Gson(); User[] userArray gson.fromJson(userJson, User[].class); for(User user : userArray) {System.out.println(user);
}运行结果 5.2 、JSON array–List
将json数组反序列化为根–到Java对象列表:
String userJson [{name: Alex,id: 1}, {name: Brian,id:2}, {name: Charles,id: 3}];Gson gson new Gson();java.lang.reflect.Type userListType new TypeTokenArrayListUser() {}.getType();ArrayListUser userArray gson.fromJson(userJson, userListType);for (User user : userArray) {System.out.println(user);}运行结果 5.3 、JSON array–成员变量
如果Json数组是非根对象则Gson可以将JSON数组解析为成员变量。我们可以按通常的方式使用fromJson()方法将json数组解析为所需的Java数组或列表。
department.json:
{id : 1,name : HR,users : [{name: Alex,id: 1},{name: Brian,id: 2},{name: Charles,id: 3}]5.3.1、数组类型成员变量
Department.java
public class Department {private long id;private String name;private User[] users;//省略getter/setter、构造方法、toString方法
}JsonArrayToMemberArray.java
String departmentJson {id : 1, name: HR, users : [ {name: Alex,id: 1}, {name: Brian,id:2}, {name: Charles,id: 3}]};Gson gson new Gson(); Department department gson.fromJson(departmentJson, Department.class); System.out.println(department);运行结果 5.3.2、List类型成员变量
将json数组反序列化为List类型成员变量。
Department2.java:
public class Department2 {private long id;private String name;private ListUser users; //省略getter/setter、构造方法、toString方法
}转换
String departmentJson {id : 1, name: HR, users : [ {name: Alex,id: 1}, {name: Brian,id:2}, {name: Charles,id: 3}]};Gson gson new Gson(); Department2 department gson.fromJson(departmentJson, Department2.class); System.out.println(department);运行结果 6、JSON ----Set
6.1、Set–JSON
使用Gson.toJson()方法将HashSet序列化为JSON:
SetString userSet new HashSetString();userSet.add(Alex);userSet.add(Brian);userSet.add(Charles);Gson gson new Gson(); String jsonString gson.toJson(userSet); System.out.println(jsonString);运行结果 6.2、JSON–Set
使用Gson.fromJson方法和TypeToken将JSON反序列化为HashSet:
String jsonString [Alex,Brian,Charles,Alex];Gson gson new Gson(); java.lang.reflect.Type setType new TypeTokenHashSetString(){}.getType();SetString userSet gson.fromJson(jsonString, setType); System.out.println(userSet);运行结果 7、Null值处理
Gson中实现的默认行为是忽略空对象字段。
例如如果在Employee对象中未指定电子邮件即email为null则电子邮件将不会被序列化JSON输出。Gson会忽略null字段因为此行为允许使用更紧凑的JSON输出格式。
7.1、如何在序列化时允许空值
要配置Gson实例以输出null我们必须使用GsonBuilder对象的serializeNulls。
Gson gson new GsonBuilder().serializeNulls().create();8、版本支持
应用程序随着时间变化模型类也随之变化。有时候更新/删除字段可能会被打断。
所有这些更改都可以使用Since注释进行标记以跟踪模型类在这些系统使用反序列化JSON数据进行交换时与其他系统的应用程序交互不会中断。
8.1、Since注解
在Gson中可以使用Since注释维护同一对象的多个版本。可以在类字段以及将来的方法中使用此注释。它采用单个参数– ignoreVersionsAfter。
当我们为Gson实例配置版本号“ M.N”时所有标记有版本大于M.N的类字段都将被忽略。例如如果我们将Gson配置为版本号“ 1.2”则所有版本号更高的字段例如1.3、1.4…都将被忽略。
Since(1.2)
private String email;8.2、如何使用Since注解编写版本化的类
在Employee类下面我们对三个字段进行了版本控制即firstNamelastName和email。
public class Employee
{private Integer id;Since(1.0)private String firstName;Since(1.1)private String lastName;Since(1.2)private String email;
}8.3、创建具备版本支持的Gson实例
要创建使用过Since注解的Gson实例需要使用GsonBuilder.setVersion()方法:
Gson gson new GsonBuilder().setVersion(1.1).create();8.4、实例
8.4.1、 具备版本支持的序列化
让序列号以上的Employee对象序列化。
Employee employeeObj new Employee(1, Lokesh, Gupta, howtogoinjavagmail.com);Gson gson new GsonBuilder().setVersion(1.1).setPrettyPrinting().create();System.out.println(gson.toJson(employeeObj));输出
{id: 1,firstName: Lokesh,lastName: Gupta
}8.4.2、具备版本支持的反序列化
我们将JSON字符串反序列化为版本号为Employee的对象。
String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com};Gson gson new GsonBuilder().setVersion(1.1).setPrettyPrinting().create();Employee employeeObj gson.fromJson(json, Employee.class);System.out.println(employeeObj);输出
Employee [id1001, firstNameLokesh, lastNameGupta, emailnull]9、更改Java对象和JSON的字段名映射
在此Gson SerializedName示例中演示在序列化和反序列化过程中更改json和java对象之间的字段名称。
9.1、SerializedName
默认情况下我们假设Java模型类和JSON将具有完全相同的字段名称。
但有时情况并非如此某些名称有所不同。现在我们必须将json中的someName映射到Java类中的someOtherName。这是SerializedName注解用到的地方。
SerializedName注解指示带注解的成员变量应使用提供的名称值作为其字段名称序列化为JSON。此注解将覆盖可能一直在使用GsonBuilder类的任何FieldNamingPolicy包括默认的字段命名策略。
请注意在此注解中指定的值必须是有效的JSON字段名称。
注解包含属性
value –序列化或反序列化时所需的字段名称。alternate–反序列化时字段的备用名称。除了“值”属性外它还提供了更多可能的名称。如果有多个字段匹配一个属性则Gson将使用最后处理的那个。
9.2、序列化期时更改字段名称
让我们以只有四个字段的Employee类为例。我们要创建一个JSON其中“ email”被写为字段名“ emailId”
public class Employee
{private Integer id;private String firstName;private String lastName;SerializedName(value emailId, alternate emailAddress)private String email;
}让我们序列化一个Employee实例并查看JSON输出
Employee emp new Employee(1001, Lokesh, Gupta, howtodoinjavagmail.com);Gson gson new GsonBuilder().setPrettyPrinting().create(); System.out.println(gson.toJson(emp));输出
{id: 1001,firstName: Lokesh,lastName: Gupta,emailId: howtodoinjavagmail.com
}9.3、反序列化时更改字段名称
在将JSON反序列化为Java类的过程中映射不同的字段名称
Json:
{id: 1001,firstName: Lokesh,lastName: Gupta,email: howtodoinjavagmail.com,emailAddress: admingmail.com
}Main.java
String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com, emailAddress: admingmail.com};Gson gson new GsonBuilder().setPrettyPrinting().create(); Employee emp gson.fromJson(json, Employee.class);System.out.println(emp);输出
Employee [id1001, firstNameLokesh, lastNameGupta, emailadmingmail.com]10、排除或忽略字段
Gson允许我们从Java类中排除或忽略不希望包含在序列化和反序列化中的字段。
Gson支持许多内置机制用于排除顶级类字段和字段类型。
10.1、Expose注解
GSON Expose注解com.google.gson.annotations.Expose可用于标记对象序列化或反序列化时是否公开包括活不包括的字段。
Expose注释在要显式指定应进行序列化或反序列化的所有字段的编程方式中很有用。
10.1.1. 怎么用 Expose
Expose是可选的并提供两个配置参数
serialize –如果为true则在序列化时会在JSON中写出带有此注解的字段。deserialize –如果为true则从JSON反序列化带有此注解的字段。
Expose(serialize false)
private String lastName;Expose (serialize false, deserialize false)
private String emailAddress;10.1.2、创建Gson实例
如果我们使用 new Gson() 创建Gson并执行toJson() 和 fromJson() 方法则Expose将不会对序列化和反序列化产生任何影响。要使用此批注我们必须使用GsonBuilder类及其excludeFieldsWithoutExposeAnnotation()方法创建Gson实例。
Gson gson new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();10.2、用修饰符排除字段
10.2.1、transient 字段
默认情况下如果我们仅将字段标记为瞬时态则Gson会将字段从序列化和反序列化中排除。
请记住它无法阻止单向转换。它同时阻止了两者。
transient 具有与Expose相同的效果serialize falsedeserialize false。
Expose(serialize false)
private String lastName;private transient String emailAddress;10.2.2、其他修饰符
通过使用GsonBuilder的excludeFieldsWithModifiers()方法我们可以排除具有某些公共修饰符的字段。
例如我们要排除一个类的所有静态成员我们可以这样创建Gson对象
Gson gson new GsonBuilder().excludeFieldsWithModifiers(Modifier.STATIC).create();我们可以使用任意数量的Modifier常量来“ excludeFieldsWithModifiers”方法。例如
Gson gson new GsonBuilder().excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE).create();10.3、排除策略
如果以上任何一种技术都不适合我们那么我们可以创建自己的策略。
ExclusionStrategy用于确定是否应将字段或顶级类作为JSON输出/输入的一部分进行序列化或反序列化。
对于序列化如果shouldSkipClassClass或shouldSkipFieldfieldAttributes方法返回true则该类或字段类型将不属于JSON输出。对于反序列化如果shouldSkipClassClass或shouldSkipFieldfieldAttributes方法返回true则不会将其设置为Java对象结构的一部分。
例如在ExclusionStrategy定义下面将排除所有使用Hidden注释注释的字段:
//public interface Hidden {// some implementation here
//}// Excludes any field (or class) that is tagged with an Hidden
public class HiddenAnnotationExclusionStrategy implements ExclusionStrategy
{public boolean shouldSkipClass(Class? clazz) {return clazz.getAnnotation(Hidden.class) ! null;}public boolean shouldSkipField(FieldAttributes f) {return f.getAnnotation(Hidden.class) ! null;}
}要使用此排除策略在GsonBuilder对象中进行设置:
GsonBuilder builder new GsonBuilder();
builder.setExclusionStrategies( new HiddenAnnotationExclusionStrategy() );Gson gson builder.create();四、GsonBuilder
对于简单的用例使用’Gson gson new Gson();’ 标准配置就足够了。 但是如果打算自定义Gson的行为则可以使用GsonBuilder自定义的配置来创建新的Gson实例。
GsonBuilder类提供一个.create()方法该方法返回一个Gson实例。
Gson gson new GsonBuilder().create();1、GsonBuilder.setPrettyPrinting()–漂亮地打印JSON
默认情况下Gson将创建紧凑的JSON字符串。这对于减少通过网络传输的数据量非常有用。
但是这种紧凑的JSON对开发人员进行开发/调试应用程序时不友好。使用漂亮的打印来格式化JSON输出
Gson gson new GsonBuilder().setPrettyPrinting().create();2、FieldNamingPolicy
FieldNamingPolicy枚举在序列化期间为JSON字段名称提供了几种标准命名约定。
它有助于Gson实例将Java字段名称正确转换为所需的JSON字段名称。
注意以下任何命名约定均不会影响以SerializedName注释的字段。我们将验证使用User类的每个策略生成的名称。
User.java
public class User
{private int id;private String first_Name;private String lastName;private String _email;
}如何使用FieldNamingPolicy
User user new User(1, Lokesh, Gupta, adminhowtodoinjava.com);Gson gson new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).setPrettyPrinting().create(); System.out.println(gson.toJson(user));以下演示每种命名策略下转换的不同的名称。
2.1、FieldNamingPolicy.IDENTITY
使用此命名策略字段名称不变。这个是默认的策略
{id: 1,first_Name: Lokesh,lastName: Gupta,_email: adminhowtodoinjava.com
}2.2、FieldNamingPolicy.LOWER_CASE_WITH_DASHES
Gson会将Java字段名称从其驼峰大小写形式修改为小写的字段名称其中每个单词都用破折号-分隔。
{id: 1,first_-name: Lokesh,last-name: Gupta,_email: adminhowtodoinjava.com
}2.3、FieldNamingPolicy.LOWER_CASE_WITH_DOTS
Gson会将Java字段名称从其驼峰大小写形式修改为小写的字段名称其中每个单词都用点.分隔:
{id: 1,first_.name: Lokesh,last.name: Gupta,_email: adminhowtodoinjava.com
}2.4、FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES
Gson会将Java字段名称从其驼峰大小写形式修改为小写的字段名称其中每个单词都用下划线_分隔。
{id: 1,first__name: Lokesh,last_name: Gupta,_email: adminhowtodoinjava.com
}2.5、 FieldNamingPolicy.UPPER_CAMEL_CASE
Gson将确保序列化为JSON格式的Java字段名称的第一个“字母”大写
{Id: 1,First_Name: Lokesh,LastName: Gupta,_Email: adminhowtodoinjava.com
}2.6、FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES
Gson将确保在将Java字段名称的第一个“字母”序列化为JSON格式时将其大写并且单词之间将使用空格分隔
{Id: 1,First_ Name: Lokesh,Last Name: Gupta,_Email: adminhowtodoinjava.com
}3、GsonBuilder.serializeNulls()——空值的序列化
默认情况下Gson会在序列化过程中忽略null值。但是有时我们想序列化具有空值的字段以便它必须出现在JSON中。为此可以使用serializeNulls()方法:
Employee employeeObj new Employee(1, Lokesh, Gupta, null);Gson gson new GsonBuilder().serializeNulls().setPrettyPrinting().create(); System.out.println(gson.toJson(employeeObj));输出
{id: 1,firstName: Lokesh,lastName: Gupta,emailId: null
}4、GsonBuilder.setExclusionStrategies()
ExclusionStrategy用于确定是否应将字段或顶级类作为JSON输出/输入的一部分进行序列化或反序列化。
对于序列化如果shouldSkipClassClass方法返回true则该类或字段类型将不会在JSON中输出。对于反序列化如果shouldSkipClassClass返回true则不会将其设置为Java对象结构的一部分。
shouldSkipFieldattribute方法也是相同的规则。
在下面的示例中使用NPI注解和属于Account类的实例的成员字段不会进行序列化和反序列化。
Gson gson new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {Overridepublic boolean shouldSkipField(FieldAttributes f) {return f.getAnnotation(NPI.class) ! null;}Overridepublic boolean shouldSkipClass(Class? clazz) {return clazz.getAnnotation(Account.class) ! null;}}).setPrettyPrinting().create();5、GsonBuilder.setLenient()——宽松的JSON语法规则
在反序列化期间Gson使用了一个宽松的JsonReader类。这意味着它仅接受兼容的JSON输入。
如果JSON违反结构规则之一它将抛出MalformedJsonException。如果我们将lenient设置为true则它将忽视某些违规行为并尝试读取格式不正确的JSON。
Gson gson new GsonBuilder().setLenient().setPrettyPrinting().create();五、JsonReader
使用Gson JsonReader类该类是基于拉式的流JSON解析器。它有助于将JSON作为令牌流读取。
1、JsonReader
JsonReader是流式JSON解析器也是pull parser的示例。pull parser解析JSON令牌并将其推送到事件处理程序中。它有助于读取JSONRFC 7159编码值作为令牌流。它读取字面值字符串数字布尔值和null以及对象和数组的开始和结束定界符。令牌以深度优先顺序遍历与JSON文档中出现的顺序相同。
2、Tokens
在流模式下每个JSON数据都被视为一个单独的令牌。
当我们使用JsonReader对其进行处理时每个令牌将被顺序处理。例如
{name:Lokesh
}在使用JsonReader进行解析时以上JSON将生成4个令牌 Token 1 { Token 2 name Token 3 Lokesh Token 4 }
3、如何创建GSON JsonReader
我们可以使用它的简单构造函数创建一个JsonReader实例该实例接受java.io.Reader类型的输入流。
String json {};
JsonReader jsonReader new JsonReader( new StringReader(json) );我们可以根据JSON流的来源使用以下阅读器之一
BufferedReaderLineNumberReaderCharArrayReaderInputStreamReaderFileReaderFilterReaderPushbackReaderPipedReaderStringReader
4、读取JSON流
创建包含有效JSON源的JsonReader之后我们可以开始遍历流令牌并查看令牌值。
以下是使用JsonReader以令牌形式读取简单JSON的示例
import java.io.IOException;
import java.io.StringReader;import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;public class Main
{public static void main(String[] args) throws Exception {String json {id: 1001,firstName: Lokesh,lastName: Gupta,email: null};JsonReader jsonReader new JsonReader(new StringReader(json));jsonReader.setLenient(true);try{while (jsonReader.hasNext()) {JsonToken nextToken jsonReader.peek();if (JsonToken.BEGIN_OBJECT.equals(nextToken)) {jsonReader.beginObject();} else if (JsonToken.NAME.equals(nextToken)) {String name jsonReader.nextName();System.out.println(Token KEY name);} else if (JsonToken.STRING.equals(nextToken)) {String value jsonReader.nextString();System.out.println(Token Value value);} else if (JsonToken.NUMBER.equals(nextToken)) {long value jsonReader.nextLong();System.out.println(Token Value value);} else if (JsonToken.NULL.equals(nextToken)) {jsonReader.nextNull();System.out.println(Token Value null);} else if (JsonToken.END_OBJECT.equals(nextToken)) {jsonReader.endObject();}}} catch (IOException e) {e.printStackTrace();} finally {jsonReader.close();}}
}输出
Token KEY id
Token Value 1001Token KEY firstName
Token Value LokeshToken KEY lastName
Token Value GuptaToken KEY email
Token Value null在上面的示例中
如果JsonReader的hasNext方法具有更多令牌则返回true。peek方法返回下一个JSON令牌但不移至该令牌。随后多次调用peek将返回相同的JSON令牌。可以使用JsonToken类的常量检查返回令牌的类型。使用beginArray和endArray方法检查数组的左括号和右括号“ [”和“]”。使用beginObject和endObject方法检查对象的左括号和右括号“ {”和“}”。令牌的密钥为JsonToken.NAME类型。使用nextName方法获取密钥名称。确定令牌的类型后使用诸如nextLongnextStringnextInt等方法获取令牌的值。可以使用nextNull或skipValue使用空文字。所有next …方法都返回当前标记的值并将内部指针移至下一个。当遇到未知名称时严格的解析器应该失败并带有异常。宽大的解析器应调用skipValue以递归地跳过该值的嵌套令牌否则可能会发生冲突。
六、JsonParser
Gson JsonParser用于将Json数据解析为JsonElement的解析树从而解析为JsonObject。
JsonObject可用于使用JSON字符串中的相应键来访问值。
1、创建JsonParser
JsonParser类只有一个默认构造函数并且不需要任何参数或配置。
JsonParser parser new JsonParser();2、转化JSON
JsonParser类提供3种方法来提供JSON作为源并将其解析为JsonElements树。
JsonElement parseJsonReader json–使用JsonReader读取JSON作为令牌流并从JSON流中返回下一个值作为分析树。JsonElement parsejava.io.Reader json–使用指定的阅读器读取JSON并将JSON字符串解析为解析树。JsonElement parsejava.lang.String json–将指定的JSON字符串解析为解析树。
如果指定的文本不是有效的JSON则这三个方法都将抛出JsonParseException和JsonSyntaxException。
3、 JsonElement, JsonObject 和JsonArray
在JsonElement树中解析了JSON字符串后我们就可以使用它的各种方法来访问JSON数据元素。
例如使用一种类型检查方法找出它代表什么类型的JSON元素
jsonElement.isJsonObject();
jsonElement.isJsonArray();
jsonElement.isJsonNull();
jsonElement.isJsonPrimitive();我们可以使用相应的方法将JsonElement转换为JsonObject和JsonArray
JsonObject jsonObject jsonElement.getAsJsonObject();
JsonArray jsonArray jsonElement.getAsJsonArray();一旦有了JsonObject或JsonArray实例就可以使用其get方法从中提取字段。
4、Gson JsonParser 示例
使用JsonParser将JSON解析为JsonElement和JsonObject并使用键获取JSON值
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;public class Main
{public static void main(String[] args) throws Exception {String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com};JsonElement jsonElement new JsonParser().parse(json);JsonObject jsonObject jsonElement.getAsJsonObject();System.out.println( jsonObject.get(id) );System.out.println( jsonObject.get(firstName) );System.out.println( jsonObject.get(lastName) );System.out.println( jsonObject.get(email) );}
}输出
1001
Lokesh
Gupta
howtodoinjavagmail.com5、使用fromJson() 获取JsonObject
我们可以使用Gson实例及其fromJson方法来获得相同的结果
String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com};JsonObject jsonObject new Gson().fromJson(json, JsonObject.class);System.out.println(jsonObject.get(id));
System.out.println(jsonObject.get(firstName));
System.out.println(jsonObject.get(lastName));
System.out.println(jsonObject.get(email));输出
String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com};JsonObject jsonObject new Gson().fromJson(json, JsonObject.class);System.out.println(jsonObject.get(id));
System.out.println(jsonObject.get(firstName));
System.out.println(jsonObject.get(lastName));
System.out.println(jsonObject.get(email));6、迭代JSON树结构
这是一个完整的示例展示了如何迭代从JsonReader获得的JsonElement
JsonParser parser new JsonParser();String json { \f1\:\Hello\,\f2\:{\f3:\:\World\}};JsonElement jsonTree parser.parse(json);if(jsonTree.isJsonObject()){JsonObject jsonObject jsonTree.getAsJsonObject();JsonElement f1 jsonObject.get(f1);JsonElement f2 jsonObject.get(f2);if(f2.isJsonObject()){JsonObject f2Obj f2.getAsJsonObject();JsonElement f3 f2Obj.get(f3);}}七、自定义序列化和反序列化
Gson在默认序列化和反序列化方面提供了非常出色的功能。
不过我们可能会遇到默认和内置自定义选项无法解决我们问题的情况。在这种情况下我们可以通过两个接口JsonSerializer和JsonDeserializer使用自定义序列化和反序列化。
1、自定义序列化
1.1、JsonSerializer接口
JsonSerializer.java
public interface JsonSerializerT
{public JsonElement serialize(T value, Type type,JsonSerializationContext jsonSerializationContext) {}
}为Json创建自定义序列化程序后我们还需要通过GsonBuilder.registerTypeAdapterTypeObject注册该序列化程序。
当Gson遇到指定类型的字段时它会在序列化期间调用其回调方法serialize。
1.2、自定义序列化示例
假设我们遇到一种情况我们必须将Java对象序列化为json这样所有布尔值都应写为1或0而不是打印true或false。
让我们为该要求编写自定义序列化程序。
BooleanSerializer.java
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;public class BooleanSerializer implements JsonSerializerBoolean {public JsonElement serialize(Boolean aBoolean, Type type,JsonSerializationContext jsonSerializationContext) {if(aBoolean){return new JsonPrimitive(1);}return new JsonPrimitive(0);}
}让我们编写一个程序使用registerTypeAdapter注册JsonSerializer实例并使用该程序将Java对象序列化为json。
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;public class Main
{public static void main(String[] args) throws Exception {Employee emp new Employee(1, Lokesh, Gupta, howtodoinjavagmail.com, true);Gson gson new GsonBuilder().registerTypeAdapter(Boolean.class, new BooleanSerializer()).setPrettyPrinting().create();String json gson.toJson(emp);System.out.println(json);}
}注意程序输出键“ active”的值被序列化为1
{id: 1,firstName: Lokesh,lastName: Gupta,email: howtodoinjavagmail.com,active: 1
}2、自定义反序列化
2.1、JsonDeserializer接口
定制反序列化器必须实现JsonDeserializer接口。JsonDeserializer接口如下所示
JsonDeserializer.java
public interface JsonDeserializerT
{ public Boolean deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException;
}为Json创建自定义反序列化器之后我们还需要通过GsonBuilder.registerTypeAdapterTypeObject注册此反序列化器。
当Gson遇到指定类型的字段时它会在序列化期间调用其回调方法deserialize。
2.2、自定义反序列化示例
假设某些服务将日期字段分别分为天月和年等部分分别返回给我们。在JSON字符串中它们可能有意义但是在Java中它们只有作为单个java.time.LocalDate对象的一部分时才有意义。
employee.json
{id: 1,firstName: Lokesh,lastName: Gupta,email: howtodoinjavagmail.com,day: 11,month: 8,year: 2019
}我们要自定义反序列化并将最后三个字段组合为LocalDate对象。
我们的Employee看起来像这样。包括必要的getter和setter以及构造函数。
Employee.java
public class Employee
{private Integer id;private String firstName;private String lastName;private String email;private LocalDate dob;
}自定义反序列化器类如下所示
EmployeeDeserializer.java
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;public class EmployeeDeserializer implements JsonDeserializerEmployee
{ Overridepublic Employee deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {JsonObject jsonObject json.getAsJsonObject();LocalDate localDate LocalDate.of(jsonObject.get(year).getAsInt(),jsonObject.get(month).getAsInt(),jsonObject.get(day).getAsInt());return new Employee(jsonObject.get(id).getAsInt(), jsonObject.get(firstName).getAsString(), jsonObject.get(lastName).getAsString(), jsonObject.get(email).getAsString(), localDate);}
}注册反序列化器然后将给定的JSON解析为java对象
Main.java
public class Main
{public static void main(String[] args) throws Exception {String json {id: 1001, firstName: Lokesh, lastName: Gupta, email: howtodoinjavagmail.com, day: 11, month: 8, year: 2019};Gson gson new GsonBuilder().registerTypeAdapter(Employee.class, new EmployeeDeserializer()).create();Employee employee gson.fromJson(json, Employee.class);System.out.println(employee);}
}注意程序输出将3个单独的字段组合到单个LocalDate对象中
Employee [id1001, firstNameLokesh, lastNameGupta, emailhowtodoinjavagmail.com, dob2019-08-11]参考
【1】 Gson
【2】 Gson – Introduction
【3】 Gson – Installation
【4】 GSON - Gson
【5】 GSON – Serialize and Deserialize JSON
【6】 Gson – Pretty Printing for JSON Output
【7】 GSON – Parse JSON array to Java array or list
【8】 GSON – Serialize and deserialize JSON to Set
【9】 Gson – GsonBuilder Configuration Examples
【10】 Gson Since – Version Support
【11】 Gson SerializedName
【12】 Gson – JsonReader
【13】 Gson – JsonReader
【14】 Gson – JsonParser
【15】 GSON - JsonParser