對Json進行處理的Google Gson API教程
在上一篇文章中,我們已經接觸了針對JSON處理的Java API,你很容易就會發現,它并不容易使用,無論你是否必須將JSON轉換為Java對象,或者其他需求,你都需要寫上很多與目標JSON結構高度耦合的代碼。
這也是為什么我開始留意其他能做到自行轉換格式的API,Gson映入了我的眼簾。Gson是開源的,并已被廣泛應用于JSON和Java中,Gson使用Java反射API,提供了諸多易于使用的方式將JSON轉換為Java,反之亦然。
你可以從google的代碼站點下載到Gson的jar文件,或者如果你正在使用maven,那么你所需要做的所有事情僅僅是添加以下依賴。
<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類型等)中。
</div>{ "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
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; }
}</pre>
Address.java
</div>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(); }
}</pre></div>
下面是Java程序,展示了如何將JSON轉換為Java對象,反之亦然。
EmployeeGsonExample.java
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; }
}</pre></div>
Gson是主類,它暴露出fromJson()和toJson()方法進行轉換工作,對于默認實現,可以直接創建對象,也可以使用GsonBuilder類提供的實用選項進行轉換,比如整齊打印,字段命名轉換,排除字段,日期格式化,等等。
當運行以上程序時,可以看到以下Java對象的輸出。
</div>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} *</pre></div>
你可以看到,使用Gson是多么的容易,這就是為什么它在JSON處理方面如此風靡。
以上的JSON處理方式是我們所熟知的對象模型,因為整個JSON被一次性的轉換為對象了,在大多數情況下這足夠了,然而如果JSON確實非常龐大,我們不想將其全部一次性置入內存,Gson也提供了Streaming API。
我們來看一個例子,它展示了如何使用Streaming API進行JSON到Java對象的轉換。
</div>EmployeeGsonReader.javapackage 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); } } }
}</pre></div>
由于JSON是一個遞歸語言(譯注:JSON本身并不是“語言”,而是一種表示方法),我們也需要針對數組和嵌套對象遞歸地調用解析方法。JsonToken是JsonReader中next()方法所返回的Java枚舉類型,我們可以用其配合條件邏輯或switch case語句進行轉換工作。根據以上代碼,你應該能夠理解這不是一個簡單的實現,如果JSON確實非常復雜,那么代碼將會變得極難維護,所以要避免使用這種方式,除非沒有其他出路。
我們來看一下如何使用Gson Streaming API寫出Employee對象。
</div>EmployeeGsonWriter.javapackage 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(); }
}</pre></div>
從Java對象到JSON的轉換,與使用streaming API解析相比,相對容易一些,默認情況下JsonWriter會以一種緊湊的格式寫入JSON,但也可以設置縮進進行整齊打印。
這就是Gson API演示教程的所有內容,如果你遇到任何問題,請告訴我。以下鏈接可以下載項目,你可以玩一玩Gson提供的多種選項。
</div> 原文鏈接: Pankaj Kumar 翻譯: ImportNew.com - Justin Wu
譯文鏈接: http://www.importnew.com/14509.html本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關經驗
相關資訊
sesese色