一、简介
JSON是一种轻量级的数据交换格式。相对于xml解析方式来说,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度。JSON是现在最理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
JSON解析有几种方式,本文将对传统解析、使用Gson和FastJson三种方法进行使用。
Gson是Google提供的一种解析json数据的框架,编码简洁,官方推荐。
Fastjson是一个Java语言编写的高性能功能完善的JSON库,它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。
二、符号
JSON就是一串字符串 只不过元素会使用特定的符号标注。
{} 双括号表示对象
[] 中括号表示数组
"" 双引号内是属性或值
: 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象),不同的键值对之间以逗号相隔
所以 {"name": "abc"} 可以理解为是一个包含name为Michael的对象 而[{"name": "abc"},{"name": "def"}]就表示包含两个对象的数组 当然了,你也可以使用{"name":["abc","def"]}来简化上面一部,这是一个拥有一个name数组的对象
三、JSON解析
1、传统JSON解析
1)创建与存放数据
Api在org.json包下。
创建JSON对象:JSONObject jsonObject = new JSONObject();
JSONObject重载了几个构造方法,可以通过不同的参数来进行构造:
public JSONObject()
public JSONObject(Map copyFrom)
public JSONObject(JSONTokener readFrom) throws JSONException
public JSONObject(String json) throws JSONException
public JSONObject(JSONObject copyFrom, String[] names) throws JSONException
创建JSON数组:JSONArray jsonArray = new JSONArray();
与JSONObject类似也可以传入不同参数构造,例如传入已有jsonString等。
向其中存放数据:
jsonObject.put(key, value),value为空时从map中remove该条数据。
jsonObject.putOpt(key, value),key或value为空时,不做任何操作直接return。
阅读JSONObject类源码可以看到,构建JSONObject对象时,实例化了一个LinkedHashMap<String, Object>,所有的数据就存放在这个map中。其中put、get等方法后都接了一个throws JSONException,用于存放或解析出错抛出来,所以使用对应方法时需要try catch。toString方法可直接将JSONObject对象转换为字符串。
JSONArray内部是一个ArrayList来存储数据。
2)解析数据
两种方式使用对应数据类型的方法通过key取出数据。
第一种是get方法,例如jsonObject.getString(“name”)。在找不到该key的时候,会抛出JSONException("No value for " + name)。在找到该key时,从map中取出value,是一个Object,然后通过JSON类中的静态方法转换成对应类型,例如JSON.toInteger(object),若其值不为对应的类型,则会抛出JSONException("Value " + actual + " at " + indexOrName + " of type " + actual.getClass().getName() + " cannot be converted to " + requiredType)。所以使用get方法时必须try catch。
第二种是opt方法,例如jsonObject.optString(“name”),在找不到该key或者其不为对应类型时,返回一个默认值,这个默认值可以是JSONObject所给的(例如optInt(String name)),也可以自己传入(例如optInt(String name, int fallback))。
例:
定义一个JavaBean类UserInfo:
public class UserInfo {
public long uid = -1;
public String userName;
public long getUid() {
return uid;
}
public String getUserName() {
return userName;
}
}
JavaBean解析:
UserInfo userInfo= new UserInfo();
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONObject userObject = jsonObject.getJSONObject("userinfo");
userInfo.uid = userObject .getLong("uid");
userInfo.userName = userObject .getString("username");
} catch (Exception e) {
// TODO: handle exception
}
List数组解析:
List list = new ArrayList();
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("userinfos");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject userObject = jsonArray.getJSONObject(i);
UserInfo userInfo= new UserInfo();
userInfo.uid = userObject .getLong("uid");
userInfo.userName = userObject .getString("username");
list.add(userInfo);
}
} catch (Exception e) {
// TODO: handle exception
}
2、GSON解析
1)创建与存放数据
需要导入’com.google.code.gson:gson:2.8.4’依赖。
创建JSON对象:JsonObject jsonObject = new JsonObject();
创建JSON数组:JsonArray jsonArray = new JsonArray(); 向其中存放数据:jsonObject.addProperty(key, value);
阅读JsonObject类源码,该类是继承于JsonElement类,数据是用一个LinkedTreeMap<String, JsonElement>来存储,在往其中放入数据时,会先将数据存入放入JsonElement的子类,然后再放入map中。
JsonArray也是JsonElement的子类,其中数据是由ArrayList来保存。
2)解析数据 JsonObject也有对应的取数据方法,不过由于是以JsonElement类的形式保存,所以第一步是取出JsonElement对象,直接使用jsonObject.get(),然后再从JsonElement对象中调用对应数据类型的方法取出数据,例如jsonObject.get(“name”).getAsString(),由于取出JsonElement对象可能为空,此时需注意一下空指针的处理。
UserInfo userInfo= new UserInfo();
JsonObject jsonObject = new JsonParser().parse(jsonString).getAsJsonObject();
JsonObject userObject = jsonObject.get("userinfo").getAsJsonObject();
userInfo.uid = userObject .get("uid").getAsLong();
userInfo.userName = userObject .get("username").getAsString();
JsonObject可以像传统的JSON解析一样一个数据一个数据读取,只是中间多了一层JsonElement,不过这样用的话GSON的存在就没多大意义了。Gson类中已经封装好了对各种JavaBean的序列化和解析,可以直接调用方法解析。
构建Gson实例:Gson gson = new Gson();
JavaBean转换为String:
public static String toJson(Object object) {
try {
return gson.toJson(object);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
return null;
}
String转换为JavaBean:
public static <T> T fromJson(String json, Class<T> classOfT) {
try {
return gson.fromJson(json, classOfT);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
return null;
}
classOfT为需要转换成的JavaBean类。 或者
public static <T> T fromJson(String json, Type typeOfT) {
try {
return gson.fromJson(json, typeOfT);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
return null;
}
typeOfT为List这种泛型,此方法主要用来解析JsonArray。
3、fastjson解析
1)创建与存放数据
需要导入'com.alibaba:fastjson:1.2.31'依赖。
创建JSON对象:JSONObject jsonObject = new JSONObject();
fastjson的JSONObject是继承于一个自定义个JSON类,里面同样通过一个Map<String, Object>来存储数据。与原生解析类似也可以通过传入不同的参数以不同的方式构建该对象:
public JSONObject()
public JSONObject(Map<String, Object> map)
public JSONObject(boolean ordered)
public JSONObject(int initialCapacity)
public JSONObject(int initialCapacity, boolean ordered)
initialCapacity表示限定map的容量,ordered为true时构建LinkedHashMap,为false时构建HashMap,也可以直接传入一个已有的map实例。
创建JSON数组:JSONArray jsonArray = new JSONArray();
JSONArray同样可以通过不同的参数进行不同的构造。
向其中存放数据:jsonObject.put(key, value);
JSONObject类还实现了map的接口,map的方法例如containsKey()、containsValue()、clear()、等可以直接调用。
2)解析数据
fastjson单个读取基础数据类型基本跟传统读取没有区别,调用对应的get方法就好了,不同的是多了很多封装数据类型,例如Date、BigInteger、BigDecimal等,并且可以直接调用getObject(String key, Class clazz)来解析自定义的JavaBean,比Gson用起来还方便。
UserInfo userInfo= new UserInfo();
JSONObject jsonObject = new JSONObject(jsonString);
JSONObject userObject = jsonObject.getJSONObject("userinfo");
userInfo.uid = userObject .getLongValue("uid");
userInfo.userName = userObject .getString("username");
JSON类中定义了很多静态方法,类似于Gson类,主要用来转换JavaBean以及List等数据类型。
JavaBean、List或Map转String:JSON.toJSONString(object);
String转JavaBean:JSON.parseObject(jsonString, JavaBean.class);
String转List:JSON.parseArray(jsonString, JavaBean.class);
String转List<Map<String,Object>>:JSON.parseObject(jsonString, new TypeReference<List<Map<String,Object>>>(){});