美文网首页
Android Json介绍和Gson使用

Android Json介绍和Gson使用

作者: BrightLight | 来源:发表于2018-09-01 17:07 被阅读0次
    一、什么是json?

    1. 官方定义
    Json(JavaScript Object Notation)是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。他基于 JavaScript ProgrammingLanguage,Standard ECMA-262 3rd Edition-December 1999的一个子集。json采用完全独立于语言的文本格式,但是也使用了类似C语言家族的习惯(包括 C、C++ 、C#、Java 、JavaScript、Per1、Python等)。这些特性使Json成为理想的数据交换语言;
    json建构和两种结构

    • "名称 / 值 " 对的集合( A collection of name/value pairs )。不同语言中,他被理解为对象(Object),记录(record),结构(struct),字典(dictionary), 哈希表(hash table),有键列表(keyed list),或者关联数组(associative array);
    • 值的有序列表(An ordered list of value),在大部分语言中,他被理解为数组;

    Json具有以下这些形式:

    • 对象是一个无序的 " ’名称/值' 对 " 集合。一个对象 以 " { " 开始, " } "结束。每个 ”名称“ 后跟一个 ” :” (冒号) ;" '名称/值‘ 对" 之间使用 “,” (逗号)分割: 对象“‘名称/值’”对集合.png
    • 数组是值(value)的有序集合。一个数组以 “[”(左中括号)开始,“]”(右中括号)结束。值之间使用 “,”(逗号)分割: 数组有序集合.png
    • 字符串(String)是由双引号包围的任意Unicode字符的集合,使用反斜线转义,一个字符(character)即一个单独的字符串(character string): 字符串.png
    • 数值(Number)也与C或者Java中的数值非常相似,除去位层使用的八进制与十六进制格式,除去一些编码细节: 数值.png
    • 空白可以加入任何符号之间

    2. 简单理解
    Json就是一串字符串,只不过元素会使用特定的符号标注
    { } 双括号表示对象
    [ ] 中括号表示数组
    " " 双引号内是属性或值
    : 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象)
    例:{“name" : "小苏"} :一个包含name为小苏的对象
    [ { "name" : "小苏”},{ "name" : "xiaosu" } ] :表示包含两个对象的数组
    { "name" : [ "小苏","xiaosu" ] } : 简化上一个例子,这是一个拥有name数组的对象

    二、Json数据的组装和原始解析
    json解析和组装json数据,主要通过Java自带的org.json包中的类: org.json结构.png
    • 拼接Json数据
      1.JSONObject对象,实例JSONObject对象,然后就可以使用put()方法放入需要的数据 2.JSONArray数组,实例JSONObject对象,然后就可以使用put()方法放入需要的数据 3.使用举例
    JSONObject jsonObject = new JSONObject();      //定义对象
    jsonObject.put("name","小苏");                 //存入一个字符串  key是“name” ,值为“小苏”
    jsonObject.put("age",28);                          //存入一个int类型 key为“age”,值为28
    System.out.println( jsonObject.toString());       // ---->   {"age":28,"name":"小苏"}
    
    JSONArray jsonArray = new JSONArray();    //声明数组
    jsonArray.put(1);
    jsonArray.put("hah");
    jsonArray.put(true);
    jsonArray.put(0,"第一");
    System.out.println(jsonArray.toString());           //  ---> ["第一","hah",true]
    
    jsonObject.put("array",jsonArray);                  //对象中放入数组
    System.out.println(jsonObject.toString());        //----> {"array":["第一","hah",true],"age":28,"name":"小苏"}
    
    • 解析Json数据
         当我们对一个Json数据进行解析时,我们应该已经定义好的json的数据结构,所以我们可以根据Json的数据结构进行解析,以下开始进行解析:
        如果取值的key不存在则会报异常
        1. 所有的 "{}" 看做是一个对象,即JSONObject ,在实例时传入要解析的参数类型
      2. 所有的“ [ ] ” 看做是一个JSONArray ;   3. 取值,JSONObject取值        JOSNArray取值
    三、解析工具Gson

    使用google提供的Gson :github地址
    gradle依赖:

     implementation 'com.google.code.gson:gson:2.8.5'
    

    以下是依据Gson官网翻译的几个简单使用例子

    (一)、Primitives Examples 原始数据例子
    Gson gson = new Gson() ;
    //Serialization
    gson.toJson(1) ;    //--> 1
    gson.toJson("abcd") ;       // --> "abcd"
    gson.toJson(new Long(10)) ;     // --> 10 
    int[] values = {1,2,3} ;        
    gson.toJson(values) ;       // ---> [1,2,3]
    //Deserialization
    int one = gson.fromJson("1",int.class) ;
    Integer one = gson.fromJson("1",Integer.class) ;
    Lone one = gson.fromJson("1",Long.class) ;
    Boolean false = gson.fromJson("false",Boolean.class);
    String str = gson.fromJson("\"abcd\"",String.class) ;       //--->abcd
    String str = gson.fromJson("abcd",String.class) ;               //--->abcd
    String[] antherStr = gson.fromJson(" [\"abcd\" ]",String[].class) ;     //转为了String[] 对象
    
    (二)、Object Examples 对象数据例子
    class BagOfPrimitives{
          private int value1 = 1 ;
          private String value2 = "abcd" ;
          private transient int values = 3 ;
          private String values4 = null;
    }
    //Serialization 
      BagOfPrimitives obj = new BagOfPrimitives() ;
      Gson gson = new Gson() ;
      String json =  gson.toJson(obj) ;     //  --->  json is :  {"value2":"abcd","value1":1}
    //Deserialization 
      BagOfPrimitives obj2 = gson.fromJson(json,BagOfPrimitives.class) ;            //---->  obj2 is just like obj 
    

    Finer points with Objects : Gson处理对象数据中需要注意的细节:

    • 推荐并且最好使用私有字段
    • 不需要是用任何注释来表示一个字段进行序列化和反序列化,默认情况下当前类(包括父类)中的所有字段都包括在内
    • 如果一个字段被标记为transient,默认情况下他会被忽略不包含在Json序列化和反序列化中
      会正确处理null
    • 当序列化时,输出中会省略空字段
    • 在反序列化时,Json中缺少的条目会导致将对象中的相应字段设置为其默认值,对象类型为null,数字类型为0 ,布尔类型为false;
    • If a field is synthetic, it is ignored and not included in JSON serialization or deserialization.
    • 与内部类、匿名类和本地类中的外部类对应的字段被忽略,不包括在序列化和反序列化中
    (三)、Nested Classes(including Inner Classes) 嵌套类(包括内部类)
    内部类无法被直接序列化,
     public class A {
        private String a ;
          class B {
            public  String b ;
            public B() {
            //No args constructor for B 
            }
        }
    }
    可以在父类中定义内部类在进行序列化
    public class A {
        private String a ;
        private B b ;
          class B {
            public  String b ;
            public B( String b) {
                this.b = b ;
              }
          }
        public void setA(String a){
          this.a = a ;
        }
        public void setB(B b){
            this.b = b ;
        }
    }
    //serialization
           A  a = new A () ;
            a.setA("123");
            A.B b = a.new B("456") ;
            a.setB(b);
            String json = gson.toJson(a);           //------> {"a":"123","b":{"b":"456"}}
    //Deserialization
    A da = gson.fromJson(json, A.class);    // ------> 转为了实体类A , da的a为“123”,B的b为“456”;
    
    (四)、Collections Examples (集合例子)
    Gson gson = new Gson() ;
    List<Integer> list = Arrays.asList(1,2,3,4,5) ;
    //Serialization
    String json = gson.toJson(list) ;           // json is------>  [ 1,2,3,4,5]
    //Deserialization 
    Type listType = new TypeToken<List<Integer>>(){}.getType() ;    //定义转换类型type
    List<Integer> list1 = gson.fromJson(json, listType);            //------>  list1 is same as list 
    

        集合的局限性:Gson可以序列换任意对象的集合,但不能冲他反序列化,因为用户无法指定结果转换的类型,相反,在反序列化时,集合必须是特定的泛型类型。这是有意义的,并且在遵 循量好的Java编码实践时很少出现问题;

    四、项目中运用

    1、数据结构:{"code":"0","message":"success","data":{} }
    2、数据结构:{"code":"0","message":"success","data":[] }
    在项目中做网络请求的时候,服务器返回上面两种数据格式,从中可以看到,主要参数为code、message和data,但是data的数据为{} 或为 [ ] ;
    具体处理中:可先定义一个模型基类,使用泛型表示data类型:

    public class SResult<T>{
    private String code ;
    private String message ;
    private T data ;            //  T为定义的泛型
    //get()   set()省略了。。。减少篇幅
    }
    public class SData{
    private String a ;
    private String b ;
    //  get() set()省略了。。。减少篇幅
    }
    

    SRresult 为基础模型,定义code 和 message ,另外定义泛型 data ;
    SData 为data类型中的一个对象实例;
    解析中有以下几种情况:
    1、纯对象数据解析:

    String json2 = "{\"a\":\"123a\",\"b\":\"123b\"}" ;
    //Deserialization
    Type type2 = new TypeToken<SData>(){}.getType() ;
    SData n = gson.fromJson(json2,type2) ;
    //Serialization
    String nResult1 = gson.toJson(n) ;             //System.out: {"a":"123a","b":"123b"}
    String nResult2 = gson.toJson(n,type2)  ;      //System.out: {"a":"123a","b":"123b"}
    

    2、纯数组数据解析

    String json3 = "[{\"a\":\"123a\",\"b\":\"123b\"},{\"a\":\"123a\",\"b\":\"123b\"},{\"a\":\"123a\",\"b\":\"123b\"}]" ;
    //Deserialization
    Type type3 = new TypeToken<List<SData>>(){}.getType() ;
    List<SData> j =  gson.fromJson(json3,type3) ;
    //Serialization
    String jResult1 = gson.toJson(j) ;
    String jResult2 = gson.toJson(j,type3) ;
    // 序列化结果是一样的
    //[{"a":"123a","b":"123b"},{"a":"123a","b":"123b"},{"a":"123a","b":"123b"}]
    

    3、对象嵌套对象的泛型转换

    String json1 = "{\"code\":\"100\",\"message\":\"返回值data为对象\",\"data\":{ \"a\":\"123a\",\"b\":\"123b\"}}" ;
    //Deserialization
    Type type1 = new TypeToken<SResult<SData>>(){}.getType() ;
    SResult<SData> m = gson.fromJson(json1, type1);
    //Serialization
    String result = gson.toJson(m);     // System.out: {"code":"100","data":{"a":"123a","b":"123b"},"message":"返回值data为对象"}
    String result1 = gson.toJson(m,type1);  //System.out: {"code":"100","data":{"a":"123a","b":"123b"},"message":"返回值data为对象"}
    

    4、对象嵌套数组的泛型转换

    String json4 = "{\"code\":\"100\",\"message\":\"返回值data为数组\",\"data\":[{\"a\":\"123a\",\"b\":\"123b\"}]}";
    //Deserialization
    Type type4 = new TypeToken<SResult<List<SData>>>(){}.getType() ;
    SResult<List<SData>>  k = gson.fromJson(json4,type4);
    //Serialization
    String kResult1 = gson.toJson(k) ;
    String kResult2 = gson.toJson(k,type4) ;
    //System.out: {"code":"100","data":[{"a":"123a","b":"123b"}],"message":"返回值data为数组"}
    

    针对泛型Deserialization可封装一个方法:

    public <T> SResult<T> deserializationGson(String json){
        Type type = new TypeToken<SResult<T>>(){}.getType();
        return new Gson().fromJson(json,type) ;
    }
    

    调用实例:

    String json4 = "{\"code\":\"100\",\"message\":\"返回值data为数组\",\"data\":[{\"a\":\"123a\",\"b\":\"123b\"}]}";
    SResult<List<SData>>  k = deserializationGson(json4);
    String serializationJson = gson.toJson(k) ;
    System.out.println("4 對象嵌套数组泛型转换---> " + serializationJson );
    //4 對象嵌套数组泛型转换---> {"code":"100","data":[{"a":"123a","b":"123b"}],"message":"返回值data为数组"}
    SResult<SData> m = deserializationGson(json1);
    serializationJson = gson.toJson(m) ;
    System.out.println("1 對象泛型转换---> " + serializationJson );
    //1 對象泛型转换---> {"code":"100","data":{"a":"123a","b":"123b"},"message":"返回值data为对象"}
    

    相关文章

      网友评论

          本文标题:Android Json介绍和Gson使用

          本文链接:https://www.haomeiwen.com/subject/vjcuwftx.html