Android常用框架----json解析系列框架

上篇介绍了常用的网络请求系列框架(http://blog.csdn.net/siwenyy/article/details/74932000),接下来开始介绍json解析系列框架。


JSON: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度。

1.JSON和XML的数据可读性基本相同
2.JSON和XML同样拥有丰富的解析手段
3.JSON相对于XML来讲,数据的体积小
4.JSON与JavaScript的交互更加方便
5.JSON对数据的描述性比XML较差
6.JSON的速度要远远快于XML

一、JSON解析之传统的JSON解析(android内置的org.json)

1、生成JSON字符串

public static String createJsonString(String key, Object value) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(key, value);
        return jsonObject.toString();
    }

2、解析JSON字符串

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;

import com.android.myjson.domain.Person;

/**
 * 完成对json数据的解析
 * 
 */
public class JsonTools {

    //解析JavaBean对象
    public static Person getPerson(String key, String jsonString) {
        Person person = new Person();
        try {
            JSONObject jsonObject = new JSONObject(jsonString);
            JSONObject personObject = jsonObject.getJSONObject("person");
            person.setId(personObject.getInt("id"));
            person.setName(personObject.getString("name"));
            person.setAddress(personObject.getString("address"));
        } catch (Exception e) {
            // TODO: handle exception
        }
        return person;
    }

    //解析list集合
    public static List getPersons(String key, String jsonString) {
        List list = new ArrayList();
        try {
            JSONObject jsonObject = new JSONObject(jsonString);
            // 返回json的数组
            JSONArray jsonArray = jsonObject.getJSONArray(key);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject2 = jsonArray.getJSONObject(i);
                Person person = new Person();
                person.setId(jsonObject2.getInt("id"));
                person.setName(jsonObject2.getString("name"));
                person.setAddress(jsonObject2.getString("address"));
                list.add(person);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }

    //解析list集合
    public static List<string> getList(String key, String jsonString) {
        List<string> list = new ArrayList<string>();
        try {
            JSONObject jsonObject = new JSONObject(jsonString);
            JSONArray jsonArray = jsonObject.getJSONArray(key);
            for (int i = 0; i < jsonArray.length(); i++) {
                String msg = jsonArray.getString(i);
                list.add(msg);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }

    //解析嵌套map集合的list集合
    public static List<map<string, object="">> listKeyMaps(String key,String jsonString) {
        List<map<string, object="">> list = new ArrayList<map<string, object="">>();
        try {
            JSONObject jsonObject = new JSONObject(jsonString);
            JSONArray jsonArray = jsonObject.getJSONArray(key);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject2 = jsonArray.getJSONObject(i);
                Map<string, object=""> map = new HashMap<string, object="">();
                Iterator<string> iterator = jsonObject2.keys();
                while (iterator.hasNext()) {
                    String json_key = iterator.next();
                    Object json_value = jsonObject2.get(json_key);
                    if (json_value == null) {
                        json_value = "";
                    }
                    map.put(json_key, json_value);
                }
                list.add(map);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }
}

3、使用JSONObject解析JSON数据

待解析的JSON格式的文件如下:

[{"id":"5", "version":"1.0", "name":"xiaowang"},
 {"id":"10", "version":"2.0", "name":"lisi"}]

官方提供的,不需要导入第三方jar包

//方法一:使用JSONObject
 private void parseJSONWithJSONObject(String JsonData) {
     try
     {
          JSONArray jsonArray = new JSONArray(jsonData);
          for (int i=0; i < jsonArray.length(); i++)    {
              JSONObject jsonObject = jsonArray.getJSONObject(i);
              String id = jsonObject.getString("id");
              String name = jsonObject.getString("name");
              String version = jsonObect.getString("version");

              System.out.println("id" + id + ";name" + name + ";version" + version);
         }
     }
     catch (Exception e)
     {
        e.printStackTrace();
     }
 }
定义一个JSON数组,用于将服务器返回的数据传入到一个JSONArray对象中; 然后循环遍历这个JSONArray,从中取出每一个元素(JSONObject对象),接下来只需调用getString()方法即可将数据取出。

二、JSON解析之GSON

首先需要添加GSON的jar包或添加依赖

compile'com.google.code.gson:gson:2.7'

1、生成JSON字符串

import com.google.gson.Gson;

public class JsonUtils {

    public static String createJsonObject(Object obj) {
        Gson gson = new Gson();
        String str = gson.toJson(obj);
        return str;

    }
}

2、解析JSON

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

;
public class GsonTools {

    public GsonTools() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @param 
     * @param jsonString
     * @param cls
     * @return
     */
    public static  T getPerson(String jsonString, Class cls) {
        T t = null;
        try {
            Gson gson = new Gson();
            t = gson.fromJson(jsonString, cls);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return t;
    }

    /**
     * 使用Gson进行解析 List
     * 
     * @param 
     * @param jsonString
     * @param cls
     * @return
     */
    public static  List getPersons(String jsonString, Class cls) {
        List list = new ArrayList();
        try {
            Gson gson = new Gson();
            list = gson.fromJson(jsonString, new TypeToken<list>() {
            }.getType());
        } catch (Exception e) {
        }
        return list;
    }

    /**
     * @param jsonString
     * @return
     */
    public static List<string> getList(String jsonString) {
        List<string> list = new ArrayList<string>();
        try {
            Gson gson = new Gson();
            list = gson.fromJson(jsonString, new TypeToken<list<string>>() {
            }.getType());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }

    public static List<map<string, object="">> listKeyMaps(String jsonString) {
        List<map<string, object="">> list = new ArrayList<map<string, object="">>();
        try {
            Gson gson = new Gson();
            list = gson.fromJson(jsonString,
                    new TypeToken<list<map<string, object="">>>() {
                    }.getType());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }
}

3、基于(一 中使用JSONObject解析JSON数据解析)

//方法二:使用GSON
private void parseJSONWithGSON(String JsonData) {
    Gson gson = new Gson();
    List applist = gson.fromJson(jsonData,
        new TypeToken>() {}.getType());
    for(App app : applist) {
         System.out.println("id" + app.getId() + ";name" + app.getName() + ";version" + app.getVersion());
    }
}

根据JSON数据内容需要定义一个类,用存放数据,如App类:

public class App {
    private String id;
    private String name;
    private String version;
    public String getId() {
        return id;
    }  

    public void setId(String id) {
        this.id = id;
    }

    //......
}

如只有一组数据,则可以直接调用如下代码 

GSON gson = new GSON();
App app = gson.fromJson(jsonData, App.class);

如果有多组数据,则需要借助TypeToken将期望解析成的数据类型传入fromJson()方法中

List app = gson.fromJson(jsonData, new TypeToken<<List>> ().getType());
备注:TypeToken的使用非常简单,如上面的代码,只要将需要获取类型的泛型类作为TypeToken的泛型参数构造一个匿名的子类,就可以通过getType()方法获取到我们使用的泛型类的泛型参数类型。

三、JSON解析之FastJSON

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

public class JsonTool {

    public static  T getPerson(String jsonstring, Class cls) {
        T t = null;
        try {
            t = JSON.parseObject(jsonstring, cls);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return t;
    }

    public static  List getPersonList(String jsonstring, Class cls) {
        List list = new ArrayList();
        try {
            list = JSON.parseArray(jsonstring, cls);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return list;
    }

    public static  List<map<string, object="">> getPersonListMap1(
            String jsonstring) {
        List<map<string, object="">> list = new ArrayList<map<string, object="">>();
        try {
            list = JSON.parseObject(jsonstring,
                    new TypeReference<list<map<string, object="">>>() {
                    }.getType());

        } catch (Exception e) {
            // TODO: handle exception
        }

        return list;
    }
}

四、使用Jackson

public static void parseJSONWithJackson(String jsonData) {  
    ObjectMapper mapper = new ObjectMapper();  
    try {  
         App app = mapper.readValue(jsonData, App.class);
     System.out.println("id" + app.getId() + ";name" + app.getName() + ";version" + app.getVersion());
   } catch (JsonParseException e) {
     e.printStackTrace(); 
   } catch (JsonMappingException e) {
     e.printStackTrace(); 
   } catch (IOException e) {
     e.printStackTrace(); 
   } 
} 

其中需要使用到:
jackson-databind.jar :核心包(必须),提供基于“流模式”解析的API【JsonPaser(json流取),JsonGenerator(json流输出)】
jackson-annotations.jar:数据绑定包(可选),提供基于“对象绑定”和“树模型”相关API。【ObjectMapper,JsonNode(树节点)】
jackson-core.jar:注解包(可选),提供注解功能。

五、以上四种json解析框架的对比

1、org.json:因为android Studio自带的org.json解析 XML 文件时会将整个 XML 文件的内容解析成树型结构存放在内存中并创建新对象,比较消耗时间和内存,解析速度和效率慢,解析方式和性能完败Gson等开源框架,导致org.json慢慢的也在被淘汰。

2、Google的Gson(Github:https://github.com/google/gson)
Google提供的用来java对象和JSON数据之间进行映射的JAVA类库,可以将一个JSON字符转成一个java对象,反过来也OK。是目前功能最全的Json解析神器。
主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。
在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。类里面只要有get和set方法。
完全可以将复杂类型的json到bean或bean到json的转换。
在功能上面无可挑剔,但是性能上面比FastJson有所差距。

优势

快速,高效 
代码量少 
面向对象 
数据传输解析方便 
可按需解析

注意事项

1、内部嵌套的类必须是static的,要不然解析会出错; 
2、类里面的属性名必须跟Json字段里面的Key是一模一样的; 
3、内部嵌套的用[]括起来的部分是一个List,所以定义为 public List< B> b,而只用{}嵌套的就定义为 public C c, 
是不是很简单,而且现在android studio上可以直接用插件生成实体类,那更加方便了

3、阿里巴巴的FastJson(Github:https://github.com/alibaba/fastjson)

是一个用Java语言编写的高性能的JSON处理器。
涉及的最基本功能就是序列化和反序列化。
无依赖,不需要例外额外的jar,能够直接跑在JDK上。
在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
采用独创的算法,将parse的速度提升到极致,超过所有json库。

优势

快速FAST(比任何一款都快) 
面向对象 
功能强大(支持普通JDK类任意java bean Class,Collection,Map,Date或者enum) 
零依赖(只需要有JDK即可) 
支持注解,全类型序列化

4、Jackson(Github:https://github.com/FasterXML/jackson)

解析原理:

基于事件驱动,与GSON相同,先创建一个对应于JSON数据的JavaBean类就可以通过简单的操作解析出所需JSON数据。但和Gson解析不同的是,GSON可按需解析,即创建的JavaBean类不一定完全涵盖所要解析的JSON数据,按需创建属性,但Jackson解析对应的JavaBean必须把Json数据里面的所有key都有所对应,即必须把JSON内的数据所有解析出来,无法按需解析。但Jackson的解析速度和效率都要比GSON高。

优势

解析效率最高 
在数据量大的情况优势尤为明显、占存少

缺点

必须完全解析文档,如果要按需解析的话可以拆分Json来读取,操作和解析方法复杂;

推荐使用情景

适用于需要处理超大型JSON文档、不需要对JSON文档进行按需解析、性能要求较高的场合

框架分析(数据来源:https://github.com/eishay/jvm-serializers/wiki/Staging-Results)

序列化性能
FastJson:1201
Jackson: 1408
Gson : 7421

反序列化性能
FastJson:1216
Jackson: 1915
Gson : 5065

Jar包大小
fastjson-1.1.26.jar(356k)
fastjson-1.1.25-android.jar(226k)
jackson-annotations-2.1.1.jar(34k)
jackson-core-2.1.1.jar(206k)
jackson-databind-2.1.1.jar(922k)
gson-2.2.2.jar(189k)

Android常用框架----json解析系列框架_第1张图片

从以上真实数据可以看出在两者转换与解析性能上的对比: 
在数据量较小时,两者的性能差距忽略不计,但如果数据量较大,超过万条时,FastJson还是略优于Gson。

总结

1、比较来说, Gson 比 fastjson 考虑更全面, 对用 URL , UUID, BIT_SET, CALENDAR 等等,都有特定的输出规则. 
2、小数量的调用 Gson 比 fastjson 快一点. (几十毫秒,可以毫不在意.猜测是因为 javassist 生成新的 Wrapper 类导致,因为还要编译的.) 
3、大数量的调用 fastjson 比 Gson 快. (千万级别的.还不太确定为什么会变快, 猜测是 gson 的反射调用,毕竟比不上 fastjson Wrapper 类的真实调用.) 
4、代码可阅读性: fastjson 比 Gson 好很多很多. 
5、fastjson 在要序列化对象的类型的判断上,使用的是 if else 。 
6、Gson 使用的是遍历 TypeAdapterFactory集合,在每个 TypeAdapterFactory 里面做判断.而且使用了 N 多的匿名内部类, 想要一眼看出有哪些 TypeAdapterFactory 的实现都很困难. 
7、如果普通日常使用,推荐使用 fastjson,简单易懂,并且是国内程序员开发,有问题可以较容易的获得支持. 
8、Gson 有对各种类型的属性支持, 如果有特殊类型json化需求或复杂结构时可以选择 gson ,并自定义扩充. 
9、如果你不需要对JSON文档进行按需解析、且性能要求较高的话,可以尝试使用Jackson.



    常用的json解析框架还有很多,以上四种是我比较熟悉的,结合网上资料做了简单汇总。但项目中我用的比较多的还是Gson,由于它使用简单、方便,所以笔者还是一见钟情他。大家可以根据自己的需求选择自己合适的框架。

资料参考:http://blog.csdn.net/zhanggang740/article/details/52278373

你可能感兴趣的:(android常用框架)