zoukankan      html  css  js  c++  java
  • Android开源库--Gson谷歌官方json解析库

    官方文档地址:http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html

    官方网站:http://code.google.com/p/google-gson/

    json官方网站:http://www.json.org/json-zh.html

    目前主流数据传输都用的是json,解析json并且转换成相应的类型就成了必经之路。

    在没有使用gson之前,原生Andoird自带有类解析json,但是实在不方便使用。

    先介绍一下Android原生的解析

    在Android中包含四个与JSON相关的类和一个Exceptions:
    JSONArray
    JSONObject
    JSONStringer
    JSONTokener
    JSONException

    (1)JSONObject:
    这是系统中有关JSON定义的基本单元,其包含一对儿(Key/Value)数值。
    它对外部(External:应用toString()方法输出的数值)调用的响应体现为一个标准的字符串(例如:{“JSON”: “Hello, World”},最外被大括号包裹,其中的Key和Value被冒号”:”分隔)。其对于内部(Internal)行为的操作格式略微,例如:初始化一个JSONObject实例,引用内部的put()方法添加数值:new JSONObject().put(“JSON”, “Hello, World!”),在Key和Value之间是以逗号”,”分隔。
    Value的类型包括:Boolean、JSONArray、JSONObject、Number、String或者默认值JSONObject.NULL object。
    有两个不同的取值方法:
    get(): 在确定数值存在的条件下使用,否则当无法检索到相关Key时,将会抛出一个Exception信息。
    opt(): 这个方法相对比较灵活,当无法获取所指定数值时,将会返回一个默认数值,并不会抛出异常。

    (2)JSONArray:
    它代表一组有序的数值。将其转换为String输出(toString)所表现的形式是用方括号包裹,数值以逗号”,”分隔(例如:[value1,value2,value3],大家可以亲自利用简短的代码更加直观的了解其格式)。这个类的内部同样具有查询行为,get()和opt()两种方法都可以通过index索引返回指定的数值,put()方法用来添加或者替换数值。
    同样这个类的value类型可以包括:Boolean、JSONArray、JSONObject、Number、String或者默认值JSONObject.NULL object。

    使用起来是这样的

    //将此json数据变成一个对象。
    JSONObject jsonObject = new JSONObject(String);
    //然后获得list里面的数据
    JSONArray jsonArray = jsonObject.getJSONArray("list");
    
    //当不知道key时,使用循环
    for(int i=0;i<jsonArray.length();i++)
        {
            JSONObject jsonOb = (JSONObject)jsonArray.opt(i);
            int tel = jsonOb.getInt("tel");
        }

    (3)JSONStringer:
    根据官方的解释,这个类可以帮助快速和便捷的创建JSONtext。其最大的优点在于可以减少由于格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntaxrules)创建JSON text。每个JSONStringer实体只能对应创建一个JSON text。

    String myString = new JSONStringer().object().key("name").value("小猪").endObject().toString();  
    //结果是一组标准格式的JSON text:{"name" : "小猪"}

    其中的.object()和.endObject()必须同时使用,是为了按照Object标准给数值添加边界。同样,针对数组也有一组标准的方法来生成边界.array()和.endArray()。

    (4)JSONTokener:
    这个是系统为JSONObject和JSONArray构造器解析JSON source string的类,它可以从source string中提取数值信息。
    (5)JSONException:
    是JSON.org类抛出的异常信息。

    自从使用了gson,一切都变得简单了

    Gson有两个重要的方法,一个是toJson,一个是fromJson,也就是序列化和反序列化。

    使用起来非常简单

    Gson gson = new Gson();
    //序列化
    MyObject myobj = new MyObject();  
    String jsonstr = gson .toJson(myobj);
    
    //反序列化
    MyObject myobj = gson.fromJson(jsonstr, MyObject.class);  
    
    //序列化数组
    String[] days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    String numbersJson = gson.toJson(numbers);
    
    //序列化集合
    List<String> myobjs = new ArrayList<String>();
    String jsonstr = gson.toJson(myobjs);
    
    //反序列化集合数组
    List<MyObject> myobjs = gson.fromJson(str, new TypeToken<ArrayList<MyObject>>(){}.getType());

    同时Gson还支持使用注解,在com.google.gson.annotation包中,有几个注解Expose, SerializedName, Since和Until,他们各有各的作用,下面使用官方例子介绍常用的注解:

    Expose

      此注解作用在属性上,表明当序列化和反序列化的时候,这个属性将会暴露给Gson对象。这个注解只有当创建Gson对象时使用GsonBuilder方式创建并调用了GsonBuilder.excludeFieldsWithoutExposeAnnotation() 方法的时候才有效,否则无效。下面是一个介绍@Expose注解如何使用的例子:

    public class User {
     @Expose private String firstName;
     @Expose(serialize = false) private String lastName;
     @Expose (serialize = false, deserialize = false) private String emailAddress;
     private String password;
    }

    如果你以new Gson()的方式创建Gson对象,toJson()方法和fromJson() 方法在序列化和反序列化的时候将会操作这4个属性。然而,如果你使用 Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()来创建Gson对象,Gson 的 toJson() 和 fromJson() 方法将会排除掉 password 字段,这是因为 password 字段没有被注解 @Expose 所标记。 这个 Gson 对象同样会排除 lastName 和 emailAddress 字段,因为注解@Expose的属性 serialize 被设置成了 false。类似的,Gson 将会在反序列化时排除掉 emailAddress 字段,因为 deserialize被设置成了 false。

    PS:

    如果不希望有某些属性,也可以使用transient屏蔽,如:

    transient int val;

    SerializedName

      此注解作用在属性上,表明这个属性在序列化成Json的时候,需要将名字序列化成注解的value属性指定的值。

      这个注解将会覆盖任何的FieldNamingPolicy, 包括默认的命名策略。下面是一个介绍@SerializedName注解如何使用的例子:

    public class SomeClassWithFields {
        @SerializedName("name") private final String someField;
        private final String someOtherField;
        public SomeClassWithFields(String a, String b) {
          this.someField = a;
          this.someOtherField = b;
        }
    }

    序列化结果是:{"name":"a","someOtherField":"b"}

    Since

    使用@Since注解去维护版本,比如你有一个REST的API,并且有多个版本的JSON,如果下一个版本JSON中增加了字段,但又不希望所有的版本都在使用这些字段的话,就可以使用

    public class Example33 {  
      public static void main(String[] args) {  
        Gson gson = new GsonBuilder().setVersion(2.0).create();  
        String json = gson.toJson(new ExampleClass());  
        System.out.println("Output for version 2.0...");  
        System.out.println(json);  
          
        gson= new GsonBuilder().setVersion(1.0).create();  
        json = gson.toJson(new ExampleClass());  
        System.out.println("
    Output for version 1.0...");  
        System.out.println(json);  
          
        gson= new Gson();  
        json = gson.toJson(new ExampleClass());  
        System.out.println("
    Output for No version set...");  
        System.out.println(json);  
      }  
    }  
       
    class ExampleClass{  
      String field=  "field";  
      // this is in version 1.0  
      @Since(1.0) String newField1 = "field 1";  
      // following will be included in the version 1.1  
      @Since(2.0) String newField2 = "field 2";  
    }  

    输出为:
    Output for version 2.0...
    {"field":"field","newField1":"field 1","newField2":"field 2"}

    Output for version 1.0...
    {"field":"field","newField1":"field 1"}

    Output for No version set...
    {"field":"field","newField1":"field 1","newField2":"field 2"}

    Until

    和Since相反,如果下一个版本JSON中删除了某个字段,就可以使用,原理同上。

    使用注释之后,我们创建gson就需要用到

    GsonBuilder

    具体设置参数如下

    Gson gson = new GsonBuilder()  
            .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性  
            .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式  
            .serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//时间转化为特定格式    
            .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//会把字段首字母大写,注:对于实体上使用了@SerializedName注解的不会生效.  
            .setPrettyPrinting() //对json结果格式化.  
            .setVersion(1.0)
          .disableHtmlEscaping()//默认是GSON把HTML 转义的,但也可以设置不转义
            .serializeNulls()//把null值也转换,默认是不转换null值的,可以选择也转换
            .create();

    PS:如果需要转换的类包括泛型,那么也需要用到TypeToken,通过这个类可以获取具体的类型

    public class ApiResult<T> {
        private int ret;
        private String msg;
        private T data;
    
        public int getRet() {
            return ret;
        }
    
        public void setRet(int ret) {
            this.ret = ret;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
    }
                    ApiResult<UserInfo> r = GsonUtils.parse(json, new TypeToken<ApiResult<UserInfo>>() {
                    }.getType());

    参考网站:

    http://jiuyuehe.iteye.com/blog/1882800

    http://shazhuzhu1.iteye.com/blog/974758

    http://jackyrong.iteye.com/blog/2004374

    http://blog.csdn.net/lk_blog/article/details/7685190

  • 相关阅读:
    LeetCode 264. Ugly Number II
    LeetCode 231. Power of Two
    LeetCode 263. Ugly Number
    LeetCode 136. Single Number
    LeetCode 69. Sqrt(x)
    LeetCode 66. Plus One
    LeetCode 70. Climbing Stairs
    LeetCode 628. Maximum Product of Three Numbers
    Leetcode 13. Roman to Integer
    大二暑假周进度报告03
  • 原文地址:https://www.cnblogs.com/leestar54/p/4212318.html
Copyright © 2011-2022 走看看