转载

对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类型等)中。

{   "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;  } } 

Address.java

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

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对象的输出。

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

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

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提供的多种选项。

http://www.journaldev.com/?wpdmact=process&did=MzAuaG90bGluaw==

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

原文链接: Pankaj Kumar 翻译:ImportNew.com -Justin Wu

译文链接:[

]

正文到此结束
Loading...