在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

对Json进行处理的Google Gson API教程

2016-12-20 13:13| 发布者: zhangjf| 查看: 475| 评论: 0

摘要: 在上一篇文章中,我们已经接触了针对JSON处理的Java API,你很容易就会发现,它并不容易使用,无论你是否必须将JSON转换为Java对象,或者其他需求,你都需要写上很多与目标JSON结构高度耦合的代码。 这也是为什么我 ...

在上一篇文章中,我们已经接触了针对JSON处理的Java API,你很容易就会发现,它并不容易使用,无论你是否必须将JSON转换为Java对象,或者其他需求,你都需要写上很多与目标JSON结构高度耦合的代码。

这也是为什么我开始留意其他能做到自行转换格式的API,Gson映入了我的眼帘。Gson是开源的,并已被广泛应用于JSON和Java中,Gson使用Java反射API,提供了诸多易于使用的方式将JSON转换为Java,反之亦然。

你可以从google的代码站点下载到Gson的jar文件,或者如果你正在使用maven,那么你所需要做的所有事情仅仅是添加以下依赖。

  1. <dependencies>
  2. <!-- Gson dependency -->
  3. <dependency>
  4. <groupId>com.google.code.gson</groupId>
  5. <artifactId>gson</artifactId>
  6. <version>2.2.4</version>
  7. </dependency>
  8. </dependencies>
复制代码

Gson是非常强大的API,它支持Java泛型,支持现成的JSON与Java对象的转换,只要对象的成员名称与JSON中的一致即可。如果针对Java bean和JSON要使用不同的名称,那么可以使用@SerializedName注解来映射JSON和Java类中的变量。

我们来看一个复杂示例,在JSON中含有嵌套对象以及数组,我们要将其映射到Java bean的属性(List、Map、Array类型等)中。

  1. {
  2. "empID": 100,
  3. "name": "David",
  4. "permanent": false,
  5. "address": {
  6. "street": "BTM 1st Stage",
  7. "city": "Bangalore",
  8. "zipcode": 560100
  9. },
  10. "phoneNumbers": [
  11. 123456,
  12. 987654
  13. ],
  14. "role": "Manager",
  15. "cities": [
  16. "Los Angeles",
  17. "New York"
  18. ],
  19. "properties": {
  20. "age": "28 years",
  21. "salary": "1000 Rs"
  22. }
  23. }
复制代码

建立Java bean类,将JSON转换为Java对象。

Employee.java

  1. package com.journaldev.json.model;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. import java.util.Map;
  5. import com.google.gson.annotations.SerializedName;
  6. public class Employee {
  7. @SerializedName("empID")
  8. private int id;
  9. private String name;
  10. private boolean permanent;
  11. private Address address;
  12. private long[] phoneNumbers;
  13. private String role;
  14. private List<String> cities;
  15. private Map<String, String> properties;
  16. public int getId() {
  17. return id;
  18. }
  19. public void setId(int id) {
  20. this.id = id;
  21. }
  22. public String getName() {
  23. return name;
  24. }
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28. public boolean isPermanent() {
  29. return permanent;
  30. }
  31. public void setPermanent(boolean permanent) {
  32. this.permanent = permanent;
  33. }
  34. public Address getAddress() {
  35. return address;
  36. }
  37. public void setAddress(Address address) {
  38. this.address = address;
  39. }
  40. public long[] getPhoneNumbers() {
  41. return phoneNumbers;
  42. }
  43. public void setPhoneNumbers(long[] phoneNumbers) {
  44. this.phoneNumbers = phoneNumbers;
  45. }
  46. public String getRole() {
  47. return role;
  48. }
  49. public void setRole(String role) {
  50. this.role = role;
  51. }
  52. @Override
  53. public String toString(){
  54. StringBuilder sb = new StringBuilder();
  55. sb.append("***** Employee Details *****n");
  56. sb.append("ID="+getId()+"n");
  57. sb.append("Name="+getName()+"n");
  58. sb.append("Permanent="+isPermanent()+"n");
  59. sb.append("Role="+getRole()+"n");
  60. sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"n");
  61. sb.append("Address="+getAddress()+"n");
  62. sb.append("Cities="+Arrays.toString(getCities().toArray())+"n");
  63. sb.append("Properties="+getProperties()+"n");
  64. sb.append("*****************************");
  65. return sb.toString();
  66. }
  67. public List<String> getCities() {
  68. return cities;
  69. }
  70. public void setCities(List<String> cities) {
  71. this.cities = cities;
  72. }
  73. public Map<String, String> getProperties() {
  74. return properties;
  75. }
  76. public void setProperties(Map<String, String> properties) {
  77. this.properties = properties;
  78. }
  79. }
复制代码

Address.java

  1. package com.journaldev.json.model;
  2. public class Address {
  3. private String street;
  4. private String city;
  5. private int zipcode;
  6. public String getStreet() {
  7. return street;
  8. }
  9. public void setStreet(String street) {
  10. this.street = street;
  11. }
  12. public String getCity() {
  13. return city;
  14. }
  15. public void setCity(String city) {
  16. this.city = city;
  17. }
  18. public int getZipcode() {
  19. return zipcode;
  20. }
  21. public void setZipcode(int zipcode) {
  22. this.zipcode = zipcode;
  23. }
  24. @Override
  25. public String toString(){
  26. return getStreet() + ", "+getCity()+", "+getZipcode();
  27. }
  28. }
复制代码

下面是java程序,展示了如何将JSON转换为Java对象,反之亦然。

EmployeeGsonExample.java

  1. package com.journaldev.json.gson;
  2. import java.io.IOException;
  3. import java.nio.file.Files;
  4. import java.nio.file.Paths;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import com.google.gson.Gson;
  10. import com.google.gson.GsonBuilder;
  11. import com.journaldev.json.model.Address;
  12. import com.journaldev.json.model.Employee;
  13. public class EmployeeGsonExample {
  14. public static void main(String[] args) throws IOException {
  15. Employee emp = createEmployee();
  16. // Get Gson object
  17. Gson gson = new GsonBuilder().setPrettyPrinting().create();
  18. // read JSON file data as String
  19. String fileData = new String(Files.readAllBytes(Paths
  20. .get("employee.txt")));
  21. // parse json string to object
  22. Employee emp1 = gson.fromJson(fileData, Employee.class);
  23. // print object data
  24. System.out.println("nnEmployee Objectnn" + emp1);
  25. // create JSON String from Object
  26. String jsonEmp = gson.toJson(emp);
  27. System.out.print(jsonEmp);
  28. }
  29. public static Employee createEmployee() {
  30. Employee emp = new Employee();
  31. emp.setId(100);
  32. emp.setName("David");
  33. emp.setPermanent(false);
  34. emp.setPhoneNumbers(new long[] { 123456, 987654 });
  35. emp.setRole("Manager");
  36. Address add = new Address();
  37. add.setCity("Bangalore");
  38. add.setStreet("BTM 1st Stage");
  39. add.setZipcode(560100);
  40. emp.setAddress(add);
  41. List<String> cities = new ArrayList<String>();
  42. cities.add("Los Angeles");
  43. cities.add("New York");
  44. emp.setCities(cities);
  45. Map<String, String> props = new HashMap<String, String>();
  46. props.put("salary", "1000 Rs");
  47. props.put("age", "28 years");
  48. emp.setProperties(props);
  49. return emp;
  50. }
  51. }
复制代码

Gson是主类,它暴露出fromJson()和toJson()方法进行转换工作,对于默认实现,可以直接创建对象,也可以使用GsonBuilder类提供的实用选项进行转换,比如整齐打印,字段命名转换,排除字段,日期格式化,等等。

当运行以上程序时,可以看到以下Java对象的输出。

  1. Employee Object
  2. ***** Employee Details *****
  3. ID=100
  4. Name=David
  5. Permanent=false
  6. Role=Manager
  7. Phone Numbers=[123456, 987654]
  8. Address=BTM 1st Stage, Bangalore, 560100
  9. Cities=[Los Angeles, New York]
  10. Properties={age=28 years, salary=1000 Rs}
  11. *****************************
复制代码

你可以看到,使用Gson是多么的容易,这就是为什么它在JSON处理方面如此风靡。

以上的JSON处理方式是我们所熟知的对象模型,因为整个JSON被一次性的转换为对象了,在大多数情况下这足够了,然而如果JSON确实非常庞大,我们不想将其全部一次性置入内存,Gson也提供了Streaming API。

我们来看一个例子,它展示了如何使用Streaming API进行JSON到Java对象的转换。

EmployeeGsonReader.java
  1. package com.journaldev.json.gson;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import com.google.gson.stream.JsonReader;
  10. import com.google.gson.stream.JsonToken;
  11. import com.journaldev.json.model.Address;
  12. import com.journaldev.json.model.Employee;
  13. public class EmployeeGsonReader {
  14. public static void main(String[] args) throws IOException {
  15. InputStream is = new FileInputStream("employee.txt");
  16. InputStreamReader isr = new InputStreamReader(is);
  17. //create JsonReader object
  18. JsonReader reader = new JsonReader(isr);
  19. //create objects
  20. Employee emp = new Employee();
  21. Address add = new Address();
  22. emp.setAddress(add);
  23. List<Long> phoneNums = new ArrayList<Long>();
  24. emp.setCities(new ArrayList<String>());
  25. emp.setProperties(new HashMap<String, String>());
  26. String key = null;
  27. boolean insidePropertiesObj=false;
  28. key = parseJSON(reader, emp, phoneNums, key, insidePropertiesObj);
  29. long[] nums = new long[phoneNums.size()];
  30. int index = 0;
  31. for(Long l :phoneNums){
  32. nums[index++] = l;
  33. }
  34. emp.setPhoneNumbers(nums);
  35. reader.close();
  36. //print employee object
  37. System.out.println("Employee Objectnn"+emp);
  38. }
  39. private static String parseJSON(JsonReader reader, Employee emp,
  40. List<Long> phoneNums, String key, boolean insidePropertiesObj) throws IOException {
  41. //loop to read all tokens
  42. while(reader.hasNext()){
  43. //get next token
  44. JsonToken token = reader.peek();
  45. switch(token){
  46. case BEGIN_OBJECT:
  47. reader.beginObject();
  48. if("address".equals(key) || "properties".equals(key)){
  49. while(reader.hasNext()){
  50. parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
  51. }
  52. reader.endObject();
  53. }
  54. break;
  55. case END_OBJECT:
  56. reader.endObject();
  57. if(insidePropertiesObj) insidePropertiesObj=false;
  58. break;
  59. case BEGIN_ARRAY:
  60. reader.beginArray();
  61. if("phoneNumbers".equals(key) || "cities".equals(key)){
  62. while(reader.hasNext()){
  63. parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
  64. }
  65. reader.endArray();
  66. }
  67. break;
  68. case END_ARRAY:
  69. reader.endArray();
  70. break;
  71. case NAME:
  72. key = reader.nextName();
  73. if("properties".equals(key)) insidePropertiesObj=true;
  74. break;
  75. case BOOLEAN:
  76. if("permanent".equals(key)) emp.setPermanent(reader.nextBoolean());
  77. else{
  78. System.out.println("Unknown item found with key="+key);
  79. //skip value to ignore it
  80. reader.skipValue();
  81. }
  82. break;
  83. case NUMBER:
  84. if("empID".equals(key)) emp.setId(reader.nextInt());
  85. else if("phoneNumbers".equals(key)) phoneNums.add(reader.nextLong());
  86. else if("zipcode".equals(key)) emp.getAddress().setZipcode(reader.nextInt());
  87. else {
  88. System.out.println("Unknown item found with key="+key);
  89. //skip value to ignore it
  90. reader.skipValue();
  91. }
  92. break;
  93. case STRING:
  94. setStringValues(emp, key, reader.nextString(), insidePropertiesObj);
  95. break;
  96. case NULL:
  97. System.out.println("Null value for key"+key);
  98. reader.nextNull();
  99. break;
  100. case END_DOCUMENT:
  101. System.out.println("End of Document Reached");
  102. break;
  103. default:
  104. System.out.println("This part will never execute");
  105. break;
  106. }
  107. }
  108. return key;
  109. }
  110. private static void setStringValues(Employee emp, String key,
  111. String value, boolean insidePropertiesObj) {
  112. if("name".equals(key)) emp.setName(value);
  113. else if("role".equals(key)) emp.setRole(value);
  114. else if("cities".equals(key)) emp.getCities().add(value);
  115. else if ("street".equals(key)) emp.getAddress().setStreet(value);
  116. else if("city".equals(key)) emp.getAddress().setCity(value);
  117. else{
  118. //add to emp properties map
  119. if(insidePropertiesObj){
  120. emp.getProperties().put(key, value);
  121. }else{
  122. System.out.println("Unknown data found with key="+key+" value="+value);
  123. }
  124. }
  125. }
  126. }
复制代码

由于JSON是一个递归语言(译注:JSON本身并不是“语言”,而是一种表示方法),我们也需要针对数组和嵌套对象递归地调用解析方法。JsonToken是JsonReader中next()方法所返回的Java枚举类型,我们可以用其配合条件逻辑或switch case语句进行转换工作。根据以上代码,你应该能够理解这不是一个简单的实现,如果JSON确实非常复杂,那么代码将会变得极难维护,所以要避免使用这种方式,除非没有其他出路。

我们来看一下如何使用Gson Streaming API写出Employee对象。

EmployeeGsonWriter.java
  1. package com.journaldev.json.gson;
  2. import java.io.IOException;
  3. import java.io.OutputStreamWriter;
  4. import java.util.Set;
  5. import com.google.gson.stream.JsonWriter;
  6. import com.journaldev.json.model.Employee;
  7. public class EmployeeGsonWriter {
  8. public static void main(String[] args) throws IOException {
  9. Employee emp = EmployeeGsonExample.createEmployee();
  10. //writing on console, we can initialize with FileOutputStream to write to file
  11. OutputStreamWriter out = new OutputStreamWriter(System.out);
  12. JsonWriter writer = new JsonWriter(out);
  13. //set indentation for pretty print
  14. writer.setIndent("t");
  15. //start writing
  16. writer.beginObject(); //{
  17. writer.name("id").value(emp.getId()); // "id": 123
  18. writer.name("name").value(emp.getName()); // "name": "David"
  19. writer.name("permanent").value(emp.isPermanent()); // "permanent": false
  20. writer.name("address").beginObject(); // "address": {
  21. writer.name("street").value(emp.getAddress().getStreet()); // "street": "BTM 1st Stage"
  22. writer.name("city").value(emp.getAddress().getCity()); // "city": "Bangalore"
  23. writer.name("zipcode").value(emp.getAddress().getZipcode()); // "zipcode": 560100
  24. writer.endObject(); // }
  25. writer.name("phoneNumbers").beginArray(); // "phoneNumbers": [
  26. for(long num : emp.getPhoneNumbers()) writer.value(num); //123456,987654
  27. writer.endArray(); // ]
  28. writer.name("role").value(emp.getRole()); // "role": "Manager"
  29. writer.name("cities").beginArray(); // "cities": [
  30. for(String c : emp.getCities()) writer.value(c); //"Los Angeles","New York"
  31. writer.endArray(); // ]
  32. writer.name("properties").beginObject(); //"properties": {
  33. Set<String> keySet = emp.getProperties().keySet();
  34. for(String key : keySet) writer.name("key").value(emp.getProperties().get(key));//"age": "28 years","salary": "1000 Rs"
  35. writer.endObject(); // }
  36. writer.endObject(); // }
  37. writer.flush();
  38. //close writer
  39. writer.close();
  40. }
  41. }
复制代码

从Java对象到JSON的转换,与使用streaming API解析相比,相对容易一些,默认情况下JsonWriter会以一种紧凑的格式写入JSON,但也可以设置缩进进行整齐打印。

这就是Gson API演示教程的所有内容,如果你遇到任何问题,请告诉我。以下链接可以下载项目,你可以玩一玩Gson提供的多种选项。

http://www.journaldev.com/?wpdmact=process&did=MzAuaG90bGluaw== 原文链接: Pankaj Kumar 翻译: ImportNew.com - Justin Wu
译文链接: http://www.importnew.com/14509.html

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-7-8 00:51

Copyright 2015-2025 djqfx

返回顶部