【转载】对Json进行处理的Google Gson API教程

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

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

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

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

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

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

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

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

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

    Employee.java

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
package com.journaldev.json.model;
 
import java.util.Arrays;
import java.util.List;
import java.util.Map;
 
import com.google.gson.annotations.SerializedName;
 
public class Employee {
 
     @SerializedName ( "empID" )
     private int id;
     private String name;
     private boolean permanent;
     private Address address;
     private long [] phoneNumbers;
     private String role;
     private List<String> cities;
     private Map<String, String> properties;
 
     public int getId() {
         return id;
     }
     public void setId( int id) {
         this .id = id;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this .name = name;
     }
     public boolean isPermanent() {
         return permanent;
     }
     public void setPermanent( boolean permanent) {
         this .permanent = permanent;
     }
     public Address getAddress() {
         return address;
     }
     public void setAddress(Address address) {
         this .address = address;
     }
     public long [] getPhoneNumbers() {
         return phoneNumbers;
     }
     public void setPhoneNumbers( long [] phoneNumbers) {
         this .phoneNumbers = phoneNumbers;
     }
     public String getRole() {
         return role;
     }
     public void setRole(String role) {
         this .role = role;
     }
 
     @Override
     public String toString(){
         StringBuilder sb = new StringBuilder();
         sb.append( "***** Employee Details *****n" );
         sb.append( "ID=" +getId()+ "n" );
         sb.append( "Name=" +getName()+ "n" );
         sb.append( "Permanent=" +isPermanent()+ "n" );
         sb.append( "Role=" +getRole()+ "n" );
         sb.append( "Phone Numbers=" +Arrays.toString(getPhoneNumbers())+ "n" );
         sb.append( "Address=" +getAddress()+ "n" );
         sb.append( "Cities=" +Arrays.toString(getCities().toArray())+ "n" );
         sb.append( "Properties=" +getProperties()+ "n" );
         sb.append( "*****************************" );
 
         return sb.toString();
     }
     public List<String> getCities() {
         return cities;
     }
     public void setCities(List<String> cities) {
         this .cities = cities;
     }
     public Map<String, String> getProperties() {
         return properties;
     }
     public void setProperties(Map<String, String> properties) {
         this .properties = properties;
     }
}

   Address.java

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
package com.journaldev.json.model;
 
public class Address {
 
     private String street;
     private String city;
     private int zipcode;
 
     public String getStreet() {
         return street;
     }
     public void setStreet(String street) {
         this .street = street;
     }
     public String getCity() {
         return city;
     }
     public void setCity(String city) {
         this .city = city;
     }
     public int getZipcode() {
         return zipcode;
     }
     public void setZipcode( int zipcode) {
         this .zipcode = zipcode;
     }
 
     @Override
     public String toString(){
         return getStreet() + ", " +getCity()+ ", " +getZipcode();
     }
}

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

    EmployeeGsonExample.java

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
package com.journaldev.json.gson;
 
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.journaldev.json.model.Address;
import com.journaldev.json.model.Employee;
 
public class EmployeeGsonExample {
 
     public static void main(String[] args) throws IOException {
         Employee emp = createEmployee();
 
         // Get Gson object
         Gson gson = new GsonBuilder().setPrettyPrinting().create();
 
         // read JSON file data as String
         String fileData = new String(Files.readAllBytes(Paths
                 .get( "employee.txt" )));
 
         // parse json string to object
         Employee emp1 = gson.fromJson(fileData, Employee. class );
 
         // print object data
         System.out.println( "nnEmployee Objectnn" + emp1);
 
         // create JSON String from Object
         String jsonEmp = gson.toJson(emp);
         System.out.print(jsonEmp);
 
     }
 
     public static Employee createEmployee() {
 
         Employee emp = new Employee();
         emp.setId( 100 );
         emp.setName( "David" );
         emp.setPermanent( false );
         emp.setPhoneNumbers( new long [] { 123456 , 987654 });
         emp.setRole( "Manager" );
 
         Address add = new Address();
         add.setCity( "Bangalore" );
         add.setStreet( "BTM 1st Stage" );
         add.setZipcode( 560100 );
         emp.setAddress(add);
 
         List<String> cities = new ArrayList<String>();
         cities.add( "Los Angeles" );
         cities.add( "New York" );
         emp.setCities(cities);
 
         Map<String, String> props = new HashMap<String, String>();
         props.put( "salary" , "1000 Rs" );
         props.put( "age" , "28 years" );
         emp.setProperties(props);
 
         return emp;
     }
}

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

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

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

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

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

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

    EmployeeGsonReader.java
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.journaldev.json.gson;
 
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.journaldev.json.model.Address;
import com.journaldev.json.model.Employee;
 
public class EmployeeGsonReader {
 
     public static void main(String[] args) throws IOException {
         InputStream is = new FileInputStream( "employee.txt" );
         InputStreamReader isr = new InputStreamReader(is);
 
         //create JsonReader object
         JsonReader reader = new JsonReader(isr);
 
         //create objects
         Employee emp = new Employee();
         Address add = new Address();
         emp.setAddress(add);
         List<Long> phoneNums = new ArrayList<Long>();
         emp.setCities( new ArrayList<String>());
         emp.setProperties( new HashMap<String, String>());
         String key = null ;
         boolean insidePropertiesObj= false ;
 
         key = parseJSON(reader, emp, phoneNums, key, insidePropertiesObj);
 
         long [] nums = new long [phoneNums.size()];
         int index = 0 ;
         for (Long l :phoneNums){
             nums[index++] = l;
         }
         emp.setPhoneNumbers(nums);
 
         reader.close();
         //print employee object
         System.out.println( "Employee Objectnn" +emp);
     }
 
     private static String parseJSON(JsonReader reader, Employee emp,
             List<Long> phoneNums, String key, boolean insidePropertiesObj) throws IOException {
 
         //loop to read all tokens
                 while (reader.hasNext()){
                     //get next token
                     JsonToken token = reader.peek();
 
                     switch (token){
                     case BEGIN_OBJECT:
                         reader.beginObject();
                         if ( "address" .equals(key) || "properties" .equals(key)){
                             while (reader.hasNext()){
                             parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
                             }
                             reader.endObject();
                         }
                         break ;
                     case END_OBJECT:
                         reader.endObject();
                         if (insidePropertiesObj) insidePropertiesObj= false ;
                         break ;
                     case BEGIN_ARRAY:
                         reader.beginArray();
                         if ( "phoneNumbers" .equals(key) || "cities" .equals(key)){
                             while (reader.hasNext()){
                                 parseJSON(reader, emp,phoneNums, key, insidePropertiesObj);
                                 }
                             reader.endArray();
                         }
                         break ;
                     case END_ARRAY:
                         reader.endArray();
                         break ;
                     case NAME:
                         key = reader.nextName();
                         if ( "properties" .equals(key)) insidePropertiesObj= true ;
                         break ;
                     case BOOLEAN:
                         if ( "permanent" .equals(key)) emp.setPermanent(reader.nextBoolean());
                         else {
                             System.out.println( "Unknown item found with key=" +key);
                             //skip value to ignore it
                             reader.skipValue();
                         }
                         break ;
                     case NUMBER:
                         if ( "empID" .equals(key)) emp.setId(reader.nextInt());
                         else if ( "phoneNumbers" .equals(key)) phoneNums.add(reader.nextLong());
                         else if ( "zipcode" .equals(key)) emp.getAddress().setZipcode(reader.nextInt());
                         else {
                             System.out.println( "Unknown item found with key=" +key);
                             //skip value to ignore it
                             reader.skipValue();
                         }
                         break ;
                     case STRING:
                         setStringValues(emp, key, reader.nextString(), insidePropertiesObj);
                         break ;
                     case NULL:
                         System.out.println( "Null value for key" +key);
                         reader.nextNull();
                         break ;
                     case END_DOCUMENT:
                         System.out.println( "End of Document Reached" );
                         break ;
                     default :
                         System.out.println( "This part will never execute" );
                         break ;
 
                     }
                 }
                 return key;
     }
 
     private static void setStringValues(Employee emp, String key,
             String value, boolean insidePropertiesObj) {
         if ( "name" .equals(key)) emp.setName(value);
         else if ( "role" .equals(key)) emp.setRole(value);
         else if ( "cities" .equals(key)) emp.getCities().add(value);
         else if ( "street" .equals(key)) emp.getAddress().setStreet(value);
         else if ( "city" .equals(key)) emp.getAddress().setCity(value);
         else {
             //add to emp properties map
             if (insidePropertiesObj){
                 emp.getProperties().put(key, value);
             } else {
                 System.out.println( "Unknown data found with key=" +key+ " value=" +value);
             }
 
         }
     }
 
}

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

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

    EmployeeGsonWriter.java
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
package com.journaldev.json.gson;
 
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Set;
 
import com.google.gson.stream.JsonWriter;
import com.journaldev.json.model.Employee;
 
public class EmployeeGsonWriter {
 
     public static void main(String[] args) throws IOException {
         Employee emp = EmployeeGsonExample.createEmployee();
 
         //writing on console, we can initialize with FileOutputStream to write to file
         OutputStreamWriter out = new OutputStreamWriter(System.out);
         JsonWriter writer = new JsonWriter(out);
         //set indentation for pretty print
         writer.setIndent( "t" );
         //start writing
         writer.beginObject(); //{
         writer.name( "id" ).value(emp.getId()); // "id": 123
         writer.name( "name" ).value(emp.getName()); // "name": "David"
         writer.name( "permanent" ).value(emp.isPermanent()); // "permanent": false
         writer.name( "address" ).beginObject(); // "address": {
             writer.name( "street" ).value(emp.getAddress().getStreet()); // "street": "BTM 1st Stage"
             writer.name( "city" ).value(emp.getAddress().getCity()); // "city": "Bangalore"
             writer.name( "zipcode" ).value(emp.getAddress().getZipcode()); // "zipcode": 560100
             writer.endObject(); // }
         writer.name( "phoneNumbers" ).beginArray(); // "phoneNumbers": [
             for ( long num : emp.getPhoneNumbers()) writer.value(num); //123456,987654
             writer.endArray(); // ]
         writer.name( "role" ).value(emp.getRole()); // "role": "Manager"
         writer.name( "cities" ).beginArray(); // "cities": [
             for (String c : emp.getCities()) writer.value(c); //"Los Angeles","New York"
             writer.endArray(); // ]
         writer.name( "properties" ).beginObject(); //"properties": {
             Set<String> keySet = emp.getProperties().keySet();
             for (String key : keySet) writer.name( "key" ).value(emp.getProperties().get(key)); //"age": "28 years","salary": "1000 Rs"
             writer.endObject(); // }
         writer.endObject(); // }
 
         writer.flush();
 
         //close writer
         writer.close();
 
     }
 
}

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

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

原文链接:  Pankaj Kumar  翻译:  ImportNew.com  Justin Wu
译文链接:  http://www.importnew.com/14509.html
转载请保留原文出处、译者和译文链接。 ]

关于作者: Justin Wu


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值