Android Json介绍和Gson使用

一、什么是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为对象"}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 1.概述2.Gson的目标3.Gson的性能和扩展性4.Gson的使用者5.如何使用Gson 通过Maven来使用...
    人失格阅读 14,231评论 2 18
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,651评论 18 139
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,928评论 2 89
  • 如题,很多做父母的都会有这样的感受。 每个家庭的实际情况不一样,所以最终的表现不同。有的孩子亲近妈妈,有的亲近爸爸...
    青杨By阅读 411评论 1 2
  • 黄昏时,来到公交车站等车回住所。眼前驶过一辆又一辆小小的汽车,我等的车还未来。闲来无聊,我听和着音乐,继续等待。忽...
    姚小曼阅读 376评论 0 0