JSON是一个标准规范,用于数据交互,规范的中文文档如下:
http://www.json.org/json-zh.html
参看规范,来对比JSON类库处理结果。
二、fastjson的一些简要说明
Fastjson是一个Java语言编写的JSON处理器。
1、遵循http://json.org标准,为其官方网站收录的参考实现之一。
2、功能qiang打,支持JDK的各种类型,包括基本的JavaBean、Collection、Map、Date、Enum、泛型。
3、无依赖,不需要例外额外的jar,能够直接跑在JDK上。
4、开源,使用Apache License 2.0协议开源。http://code.alibabatech.com/wiki/display/FastJSON/Home
如果获得Fastjson?
SVN:http://code.alibabatech.com/svn/fastjson/trunk/
WIKI:http://code.alibabatech.com/wiki/display/FastJSON/Home
Issue Tracking:http://code.alibabatech.com/jira/browse/FASTJSON
三、主要的使用入口
Fastjson API入口类是com.alibaba.fastjson.JSON,常用的序列化操作都可以在JSON类上的静态方法直接完成。
public static final Object parse(String text); // 把JSON文本parse为JSONObject或者JSONArray public static final JSONObject parSEObject(String text); // 把JSON文本parse成JSONObject public static final <T> T parSEObject(String text,Class<T> clazz); // 把JSON文本parse为JavaBean public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray public static final <T> List<T> parseArray(String text,Class<T> clazz); //把JSON文本parse成JavaBean集合 public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本 public static final String toJSONString(Object object,boolean prettyFormat); // 将JavaBean序列化为带格式的JSON文本 public static final Object toJSON(Object javaObject); 将JavaBean转换为JSONObject或者JSONArray。
测试代码:
package dhp.com.test; public class Userinfo { private String name; private int age; public Userinfo() { super(); } public Userinfo(String name,int age) { super(); this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } }
package dhp.com.test; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Vector; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; /** * fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发。 * 主要特点: * 1.快速FAST(比其它任何基于Java的解析器和生成器更快,包括jackson) 强大 * (支持普通JDK类包括任意Java Bean * 2.Class、Collection、Map、Date或enum) 零依赖(没有依赖其它任何类库除了JDK) * */ public class TestFastJson { public static void main(String[] args) { String json = "{\"name\":\"chenggang\",\"age\":24}"; String arrayAyy = "[[\'马云',50],null,[\'马化腾',30]]"; //Entity2json("zhangsan",24); //list2Json(); //Complexdata(); Deserialization(json); DateFormate(new Date()); //Json2Eetity(json); //String2JSONArray(arrayAyy); } // 实体转为Json public static void Entity2json(String name,int age) { Userinfo info = new Userinfo(name,age); String str_json = JSON.toJSONString(info); // System.out.println("实体转化为Json" + str_json); } // list转Json public static void list2Json() { List<Userinfo> list = new ArrayList<Userinfo>(); Userinfo userinfo1 = new Userinfo("lisi",15); Userinfo userinfo2 = new Userinfo("wangwu",16); list.add(userinfo1); list.add(userinfo2); String json = JSON.toJSONString(list,true); System.out.println("List集合转json格式字符串 :" + json); } // 字符数组转化为JSon private static void String2JSONArray(String arrayAyy) { JSONArray array = JSONArray.parseArray(arrayAyy); System.out.println("数组:" + array); System.out.println("数组长度: " + array.size()); Collection nuCon = new Vector(); nuCon.add(null); array.removeAll(nuCon); System.out.println("数组:" + array); System.out.println("数组长度: " + array.size()); } // 复杂数据类型 public static void Complexdata() { HashMap<String,Object> map = new HashMap<String,Object>(); map.put("username","zhangsan"); map.put("age",24); map.put("sex","男"); // map集合 HashMap<String,Object> temp = new HashMap<String,Object>(); temp.put("name","xiaohong"); temp.put("age","23"); map.put("girlInfo",temp); // list集合 List<String> list = new ArrayList<String>(); list.add("爬山"); list.add("骑车"); list.add("旅游"); map.put("hobby",list); String jsonString = JSON.toJSONString(map); System.out.println("复杂数据类型:" + jsonString); } public static void Deserialization(String json) { Userinfo userInfo = JSON.parSEObject(json,Userinfo.class); System.out.println("姓名是:" + userInfo.getName() + ",年龄是:" + userInfo.getAge()); } // 格式话日期 public static void DateFormate(Date date) { System.out.println("输出毫秒值:" + JSON.toJSONString(date)); System.out.println("默认格式为:" + JSON.toJSONString(date,SerializerFeature.WriteDateUseDateFormat)); System.out.println("自定义日期:" + JSON.toJSONStringWithDateFormat(date,"yyyy-MM-dd",SerializerFeature.WriteDateUseDateFormat)); } // Json转为实体 private static void Json2Eetity(String json) { Userinfo userInfo = JSON.parSEObject(json,Userinfo.class); System.out.println("输出对象的地址:" + userInfo.toString()); System.out.println("输出对象的名字:" + userInfo.getName()); } }
有关需要带类型的全类型序列化过程,需要调用JSON.toJSONString()方法。
需要美化输出时候,需要打开序列化美化开关,在方法中true那个参数。
四、Jackson提供了很多类和方法,而在序列化和反序列化中使用的最多的类则是ObjectMapper这个类,此类中提供了readTree(),readValue(),writeValueAsString()等方法用于转换。
package dhp.com.test2; public class Name { private String firstName; private String lastName; public Name() { } public Name(String firstName,String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String toString() { return firstName + " " + lastName; } }
package dhp.com.test2; import java.util.Date; public class Student { private int id; private Name name; private String className; private Date birthDay; public Student() { } public Student(int id,Name name,String className,Date birthDay) { super(); this.id = id; this.name = name; this.className = className; this.birthDay = birthDay; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @Override public String toString() { return "Student [birthDay=" + birthDay + ",id=" + id + ",name=" + name + ",classname=" + className + "]"; } }
package dhp.com.test2; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; import org.codehaus.jackson.type.TypeReference; public class TestJackson { public static ObjectMapper getDefaultObjectMapper() { ObjectMapper mapper = new ObjectMapper(); //设置将对象转换成JSON字符串时候:包含的属性不能为空或""; //Include.Include.ALWAYS 默认 //Include.NON_DEFAULT 属性为默认值不序列化 //Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化 //Include.NON_NULL 属性为NULL 不序列化 mapper.setSerializationInclusion(Inclusion.NON_EMPTY); //设置将MAP转换为JSON时候只转换值不等于NULL的 mapper.configure(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES,false); //mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII,true); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); //设置有属性不能映射成PO时不报错 mapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); return mapper; } public static void main(String[] args) throws Exception{ //准备数据 Name name1 = new Name("zhang","san"); Name name2 = new Name("li","si"); Name name3 = new Name("wang","wu"); Student student1 = new Student(1,name1,"一班",new Date()); Student student2 = new Student(2,name2,"二班",new Date()); Student student3 = new Student(3,name3,"三班",new Date()); List<Student> studentList = new ArrayList<Student>(); studentList.add(student1); studentList.add(student2); studentList.add(student3); Map<String,Student> studentMap = new HashMap<String,Student>(); studentMap.put("1",student1); studentMap.put("2",student2); studentMap.put("3",student3); Student json2object = null; List<Student> json2list = null; Map<String,Student> json2map = null; ObjectMapper mapper = getDefaultObjectMapper(); /* Object --> JSON */ String object4json = mapper.writeValueAsString(student1); System.out.println("Object ----> JSON"); System.out.println(object4json); System.out.println("------------------------------------------------------"); /* List<Object> --> JSON */ String listforjson = mapper.writeValueAsString(studentList); System.out.println("List<Object> ----> JSON"); System.out.println(listforjson); System.out.println("------------------------------------------------------"); /* Map<String,Object> ----> JSON */ String map4json = mapper.writeValueAsString(studentMap); System.out.println("Map<String,Object> ----> JSON"); System.out.println(map4json); System.out.println("------------------------------------------------------"); /* JSON --> Object */ json2object = mapper.readValue(object4json,Student.class); System.out.println("JSON ----> Object"); System.out.println(json2object); System.out.println("------------------------------------------------------"); /* JSON --> List<Object> */ json2list = mapper.readValue(listforjson,new TypeReference<List<Student>>() {}); System.out.println("JSON --> List<Object>"); System.out.println(json2list.toString()); System.out.println("------------------------------------------------------"); /* JSON --> Map<String,Object> */ json2map = mapper.readValue(map4json,new TypeReference<Map<String,Student>>() {}); System.out.println("JSON --> Map<String,Object>"); System.out.println(json2map.toString()); } }
注意:jackson渐次反序列化
此方法更灵活,可以只将用户感兴趣的Json串信息值提取出来。主要利用ObjectMapper提供的readTree和Jackson提供的JsonNode类来实现。
测试例子:
String test="{"results":[{"objectID":357,"geoPoints":[{"x":504604.59802246094,"y":305569.9150390625}]},{"objectID":358,"geoPoints":[{"x":504602.2680053711,"y":305554.43603515625}]}]}";
此Json串比较复杂,包含了嵌套数组的形式,具有通用性。
实现反序列化
JsonNode node= objectMapper.readTree(test); //将Json串以树状结构读入内存 JsonNode contents=node.get("results");//得到results这个节点下的信息 for(int i=0;i<contents.size();i++) //遍历results下的信息,size()函数可以得节点所包含的的信息的个数,类似于数组的长度 { System.out.println(contents.get(i).get("objectID").getIntValue()); //读取节点下的某个子节点的值 JsonNode geoNumber=contents.get(i).get("geoPoints"); for(int j=0;j<geoNumber.size();j++) //循环遍历子节点下的信息 { System.out.println(geoNumber.get(j).get("x").getDoubleValue()+" "+geoNumber.get(j).get("y").getDoubleValue()); } }
在控制台下输出的结果是:
357
504604.59802246094 305569.9150390625
358
504602.2680053711 305554.43603515625
此方法类似于XML解析中的DOM方式解析,其好处是结构明细,便于提取想要的信息。当然,其缺点也和此方法一样:耗时费空间。
五、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,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,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,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 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== 原文链接: Pankaj Kumar 翻译: ImportNew.com - Justin Wu 译文链接: http://www.importnew.com/14509.html
原文链接:https://www.f2er.com/json/289420.html