Gson详细使用,此Gson非彼Json,你值得拥有~

额~先来一句官方的话

Gson是谷歌推出的解析json数据以及将对象转换成json数据的一个开源框架. 现在json因其易读性和高效率而被广泛的使用着. 相对于java以及其它json的解析框架,Gson非常的好用.

熟悉网络编程的人知道,网络请求返回的数据格式一般要么是json,要么是xml,但是采用json格式这种方式是使用的最为广泛的。
网络请求返回的json数据时,使用JSONObject或者JSONArray来承载数据,然后把返回的数据当作一个字典,根据键取出相应的值。

现在假如网络请求返回这样一个数据:
{
“city”: “北京”,
“cityId”: “10000000001”,
“temp”: “24”,
“wd”: “南风”,
“ws”: “2级”,
“sd”: “74%”,
“wse”: “2”,
“time”: “17:45”,
“isReader”: “1”,
“Radar”: “JC_RADAR_AZ9010_JB”,
“njd”: “暂无实况\t”,
“qy”: “1005”
}
那么在使用Json在解析这段数据的时候是依据每一个Key来取值的。
那我们要一次知道如下一些键值key才能取到相应的value.
city ,cityId,temp,wd,ws,sd,wse,time,isReader,Radar;
如果在做项目的时候后台给的接口不是很多,那么采用这种方式还是可以接受的,如果后台接口没有设计好,可能要改变几个接口,增添若干个字段,或删除若干个字段,那么对于前端开发人员来说这是难以接受的,而且对于整个项目来说也是非常难以接受,对于这样的后台开发者来说,我个人觉得那是要拖出来枪毙的,因为接口一改变,对于大一点的项目来说,Android,IOS,Web,微信等等前端开发,都需要进行相应的改变,需要改变重新调整数据实体和修改相应json解析,如果项目很大的话,即便修改一点点也是非常耗时间的。曾经年少无知做过这样的项目,还好和自己的好朋友同学一起开发,不过也因此发生过严重的争执,感谢自己的当时的忍耐,没有打起来。不过现在仍然是好朋友^_^.如果当时要是知道了有Gson这吊炸天的玩意儿,也许就不会发生那么多不愉快的事情了,当然现在不仅仅只有Gson,还有fastJson也有同样的功能,好吧,下面我们来看看Gson是如何的吊炸天。

在此之前,我们需要准备gson.jar
可以到官网下载:
http://mvnrepository.com/artifact/com.google.code.gson/gson
这里写图片描述
点击下载
这里写图片描述
我下载的是最新的,2.6.2版本的,链接不上的也可以直接在这里下载

好了现在开始讲解介绍gson了
1.在调用JSON操作时,gson实例不维护任何状态。所以,你可以重复使用同一对象的多个JSON序列化和反序列化操作。
(Serialization)序列化操作如下:

import com.google.gson.Gson;
public class Demo04 {
    public static void main(String[] args) {
        Gson gson = new Gson();
        String s = gson.toJson(11111);         
        System.out.println("(11111)->"+s);
        s = gson.toJson("abcdefg");   
        System.out.println("(abcd)->"+s);
        s = gson.toJson(new Long(10)); 
        System.out.println("(10)->"+s);
        int[] values = { 1 ,2,3,4,5,6};
        s = gson.toJson(values);       
        System.out.println("(1 ,2,3,4,5,6)->"+s);
    }
}

控制台输出:
(11111)->11111
(abcd)->”abcdefg”
(10)->10
(1 ,2,3,4,5,6)->[1,2,3,4,5,6]


(Deserialization)反序列化操作如下:

import java.util.List;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Demo05 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new Gson();
        int one = gson.fromJson("1", int.class);
        System.out.println("one:" + one);
        Integer integer = gson.fromJson("1", Integer.class);
        System.out.println("integer:" + integer);
        Long long1 = gson.fromJson("1", Long.class);
        System.out.println("long1:" + long1);
        Boolean boolean1 = gson.fromJson("false", Boolean.class);
        System.out.println("boolean1:" + boolean1);
        String str = gson.fromJson("\"abc\"", String.class);
        System.out.println("str:" + str);
        List<String> list = gson.fromJson("[\"abc\",\"def\"]",
                new TypeToken<List<String>>() {
                }.getType());
        System.out.println("list:" + list);
    }

}

控制台输出:
one:1
integer:1
long1:1
boolean1:false
str:abc
list:[abc, def]

2.(对象例子)Object Examples
实体如下:

package domain;
import java.util.Date;

public class Student {
    private int id;
    private String name;
    private Date birthDay;

    public Student(){}

    public Student(int id, String name, Date birthDay) {
        super();
        this.id = id;
        this.name = name;
        this.birthDay = birthDay;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthDay() {
        return birthDay;
    }

    public void setBirthDay(Date birthDay) {
        this.birthDay = birthDay;
    }

    public String toString() {
        return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
                + name + "]";
    }

}

(Serialization)序列化操作如下:

import com.google.gson.Gson;
public class Demo03 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Weather w = new Weather("北京", "10000000001", "24", "南风", "2级", "74%",
                "2", "17:45", "1", "JC_RADAR_AZ9010_JB", "暂无实况  ", "1005");
        Gson gson = new Gson();
        System.out.println(gson.toJson(w));
    }

}

控制台输出(手动转成Json格式):
{
“city”: “北京”,
“cityId”: “10000000001”,
“temp”: “24”,
“wd”: “南风”,
“ws”: “2级”,
“sd”: “74%”,
“wse”: “2”,
“time”: “17:45”,
“isReader”: “1”,
“Radar”: “JC_RADAR_AZ9010_JB”,
“njd”: “暂无实况\t”,
“qy”: “1005”
}
(Deserialization)反序列化操作如下:

import com.google.gson.Gson;
public class Demo03 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Weather w = new Weather("北京", "10000000001", "24", "南风", "2级", "74%",
                "2", "17:45", "1", "JC_RADAR_AZ9010_JB", "暂无实况  ", "1005");
        Gson gson = new Gson();
        String json = gson.toJson(w);
        System.out.println("json输出:"+json);
        System.out.println("-----------------------------------------");
        Weather w2 = gson.fromJson(json, Weather.class);
        System.out.println("对象输出:"+w2);
    }

}

控制台输出:

json输出(便于观察,转成json格式排版):
{
    "city": "北京",
    "cityId": "10000000001",
    "temp": "24",
    "wd": "南风",
    "ws": "2级",
    "sd": "74%",
    "wse": "2",
    "time": "17:45",
    "isReader": "1",
    "Radar": "JC_RADAR_AZ9010_JB",
    "njd": "暂无实况\t",
    "qy": "1005"
}
-----------------------------------------
对象输出(便于观察,转成json格式排版,实际toString):
Weather[
    city=北京,
    cityId=10000000001,
    temp=24,
    wd=南风,
    ws=2级,
    sd=74%,
    wse=2,
    time=17: 45,
    isReader=1,
    Radar=JC_RADAR_AZ9010_JB,
    njd=暂无实况,
    qy=1005
]

3.现在来个稍微复杂一点的包含内部类
实体如下(BoyStudent 包含Student内部类):

public class Student {
    private int id;
    private String name;
    private Date birthDay;
    public Student(){}
    public Student(int id, String name, Date birthDay) {
        super();
        this.id = id;
        this.name = name;
        this.birthDay = birthDay;
    }
    public String toString() {
        return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
                + name + "]";
    }
}


public class BoyStudent {
    private String sex;
    private String intertests;
    private Student student;
    @Override
    public String toString() {
        return "Boy [sex=" + sex + ", intertests=" + intertests + ", student="
                + student + "]";
    }
    public Boy(String sex, String intertests, Student student) {
        super();
        this.sex = sex;
        this.intertests = intertests;
        this.student = student;
    }
    public Boy() {
    }
}

(Serialization)序列化,(Deserialization)反序列化操作操作如下:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new Gson();
        Student s1 = new Student(1,"s1",new Date());
        BoyStudent b1 = new BoyStudent("m", "篮球", s1);
        String json1 = gson.toJson(b1);
        System.out.println("json1:"+json1);
        System.out.println("---------------------------");
        BoyStudent bTemp = gson.fromJson(json1, BoyStudent.class);
        System.out.println("bTemp:"+bTemp);
    }

输出:

json1:
{
    "sex": "m",
    "intertests": "篮球",
    "student": {
        "id": 1,
        "name": "s1",
        "birthDay": "Mar 21, 2016 9:44:05 PM"
    }
}
---------------------------
bTemp:
BoyStudent[
    sex=m,
    intertests=篮球,
    student=Student[
        birthDay=MonMar2121: 44: 05CST2016,
        id=1,
        name=s1
    ]
]

4.在开发中那么这还是仅仅不够的,进场返回来的json数据是一个集合,那么gson能否实现呢?哈哈~那是必须的,现在来个复杂一点的。
实体如下:

public class ResponseBoyStudent {
    private int errCode;
    private String note;
    private BoyStudent boyStudent;
    public ResponseBoyStudent(int errCode, String note, BoyStudent boyStudent) {
        super();
        this.errCode = errCode;
        this.note = note;
        this.boyStudent = boyStudent;
    }
    @Override
    public String toString() {
        return "ResponseBoyStudent [errCode=" + errCode + ", note=" + note
                + ", boyStudent=" + boyStudent + "]";
    }
}

(Serialization)序列化,(Deserialization)反序列化操作操作如下:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Student s1 = new Student(1, "TFboys-1", new Date());
        Student s2 = new Student(2, "TFboys-2", new Date());
        Student s3 = new Student(3, "TFboys-3", new Date());

        BoyStudent b1 = new BoyStudent("M", "唱歌", s1);
        BoyStudent b2 = new BoyStudent("M", "跳舞", s2);
        BoyStudent b3 = new BoyStudent("M", "啥都不会", s3);

        ResponseBoyStudent rbs1 = new ResponseBoyStudent(200, "Ok", b1);
        ResponseBoyStudent rbs2 = new ResponseBoyStudent(302, "跳转", b2);
        ResponseBoyStudent rbs3 = new ResponseBoyStudent(404, "资源请求失败", null);

        List<ResponseBoyStudent> tfboys = new ArrayList<ResponseBoyStudent>();
        tfboys.add(rbs1);
        tfboys.add(rbs2);
        tfboys.add(rbs3);

        Gson gson = new Gson();
        String json = gson.toJson(tfboys);
        System.out.println(json);

        System.out.println("--------------------------------");

        List<ResponseBoyStudent> rec_tfboys = gson.fromJson(json,
                new TypeToken<List<ResponseBoyStudent>>() {
                }.getType());
        System.out.println(rec_tfboys);

    }

控制台输出:

[
    {
        "errCode": 200,
        "note": "Ok",
        "boyStudent": {
            "sex": "M",
            "intertests": "唱歌",
            "student": {
                "id": 1,
                "name": "TFboys-1",
                "birthDay": "Mar 21, 2016 10:06:54 PM"
            }
        }
    },
    {
        "errCode": 302,
        "note": "跳转",
        "boyStudent": {
            "sex": "M",
            "intertests": "跳舞",
            "student": {
                "id": 2,
                "name": "TFboys-2",
                "birthDay": "Mar 21, 2016 10:06:54 PM"
            }
        }
    },
    {
        "errCode": 404,
        "note": "资源请求失败"
    }
]
--------------------------------
[
    ResponseBoyStudent[
        errCode=200,
        note=Ok,
        boyStudent=BoyStudent[
            sex=M,
            intertests=唱歌,
            student=Student[
                birthDay=MonMar2122: 06: 54CST2016,
                id=1,
                name=TFboys-1
            ]
        ]
    ],
    ResponseBoyStudent[
        errCode=302,
        note=跳转,
        boyStudent=BoyStudent[
            sex=M,
            intertests=跳舞,
            student=Student[
                birthDay=MonMar2122: 06: 54CST2016,
                id=2,
                name=TFboys-2
            ]
        ]
    ],
    ResponseBoyStudent[
        errCode=404,
        note=资源请求失败,
        boyStudent=null
    ]
]

看到这里有木有想哭的赶脚,之前写的代码真叫尼玛一个累~
注意:好好观察哦,当404传入为空的时候,在生成Json字符串是没有boyStudent这个键值的,同时当反序列化为list对象时boyStudent是为空的!
好了看到这里,会想到另外一种需求,BoyStudent不能为空,而且它是有默认值的,但是返回来的却是null,那么在程序中像这样rec_tfboys.get(postion).getBoyStudent().get….使用是一定会报空指针异常的。总不至于不让后台传入空值吧?会不会有其他的解决办法呢?带着问题思考,既然提到这里了,答案一定是有的,再次之前就说Gson吊炸天了吧!我说的没错吧,废话不多说,直接来码代码吧~^_^

我对几个实体类稍微做了一下修改,注意观察修改了那些内容,注意哪些是变化的,哪些是没有变化的

public class Student {
    private int id;
    private String name;
    private Date birthDay;
    /////////////////////Change/////////////////////////////
    public Student(){
        this.id = 0;
        this.name = "请输入您的姓名";
        this.birthDay = new Date();
    }
    /////////////////////Change/////////////////////////////

    public Student(int id, String name, Date birthDay) {
        super();
        this.id = id;
        this.name = name;
        this.birthDay = birthDay;
    }
    public String toString() {
        return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
                + name + "]";
    }
}

public class BoyStudent {
    private String sex;
    private String intertests;
    private Student student;
    @Override
    public String toString() {
        return "BoyStudent [sex=" + sex + ", intertests=" + intertests + ", student="
                + student + "]";
    }

    public BoyStudent(String sex, String intertests, Student student) {
        super();
        this.sex = sex;
        this.intertests = intertests;
        this.student = student;
    }
    /////////////////////Change/////////////////////////////
    public BoyStudent() {
        this.sex = "M";
        this.intertests = "左手右手一个慢动作";
        this.student = new Student(1000, "请输入您的姓名", new Date());
    }
    /////////////////////Change/////////////////////////////
}

public class ResponseBoyStudent {
    private int errCode;
    private String note;
    private BoyStudent boyStudent;
    public ResponseBoyStudent(int errCode, String note, BoyStudent boyStudent) {
        super();
        this.errCode = errCode;
        this.note = note;
        this.boyStudent = boyStudent;
    }
    /////////////////////Change/////////////////////////////
    public ResponseBoyStudent(){
        boyStudent = new BoyStudent("M","睡觉",new Student());
    }
    //////////////////////////////////////////////////
    @Override
    public String toString() {
        return "ResponseBoyStudent [errCode=" + errCode + ", note=" + note
                + ", boyStudent=" + boyStudent + "]";
    }
}

我将用斜线表示出来改变的部分,一次是对其无参构造函数进行了修改,我们来看看效果是否如我们所想那样。
序列化反序列化操作操作代码未进行修改。
控制台输出:

[
    {
        "errCode": 200,
        "note": "Ok",
        "boyStudent": {
            "sex": "M",
            "intertests": "唱歌",
            "student": {
                "id": 1,
                "name": "TFboys-1",
                "birthDay": "Mar 21, 2016 10:41:43 PM"
            }
        }
    },
    {
        "errCode": 302,
        "note": "跳转",
        "boyStudent": {
            "sex": "M",
            "intertests": "跳舞",
            "student": {
                "id": 2,
                "name": "TFboys-2",
                "birthDay": "Mar 21, 2016 10:41:43 PM"
            }
        }
    },
    {
        "errCode": 404,
        "note": "资源请求失败"
    }
]
--------------------------------
[
    ResponseBoyStudent[
        errCode=200,
        note=Ok,
        boyStudent=BoyStudent[
            sex=M,
            intertests=唱歌,
            student=Student[
                birthDay=MonMar2122: 41: 43CST2016,
                id=1,
                name=TFboys-1
            ]
        ]
    ],
    ResponseBoyStudent[
        errCode=302,
        note=跳转,
        boyStudent=BoyStudent[
            sex=M,
            intertests=跳舞,
            student=Student[
                birthDay=MonMar2122: 41: 43CST2016,
                id=2,
                name=TFboys-2
            ]
        ]
    ],
    ResponseBoyStudent[
        errCode=404,
        note=资源请求失败,
        boyStudent=BoyStudent[
            sex=M,
            intertests=睡觉,
            student=Student[
                birthDay=MonMar2122: 41: 43CST2016,
                id=0,
                name=请输入您的姓名
            ]
        ]
    ]
]

**可以发现json字符串未发生改变,但是反序列化的list的内容都是部位空的,可以推出,json字符串中缺少键值的时候仍会去“调用”默认构造函数。

5.既然能让空的json反序列话为不为null的实例,那能不能返回null?不买关子了,是有的^_^.
代码很简单:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new GsonBuilder().serializeNulls().create();
        String json = gson.toJson(null);
        System.out.println(json);
    }

控制台输出:

null

为什么非要去Builder一个Gson实例呢,难道直接new 出来的不可以吗?亲测确实可以,但是这两种方式有什么区别呢?

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new Gson();
        String json = gson.toJson(null);
        System.out.println(json);
    }

控制台输出:

null

好,那我么就来观察它的区别吧!
直接上代码了
实体如下:

public class Foo {
    private final String s;
    private final int i;
    public Foo() {
        this(null, 5);
    }
    public Foo(String s, int i) {
        this.s = s;
        this.i = i;
    }
    @Override
    public String toString() {
        return "Foo [s=" + s + ", i=" + i + "]";
    }
}

(Serialization)序列化,(Deserialization)反序列化操作操作如下:
先看直接new出来的Gson

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new Gson();
        Foo foo = new Foo();
        String json = gson.toJson(foo);
        System.out.println(json);
        Foo f = gson.fromJson(json, Foo.class);
        System.out.println("f:"+f);
        json = gson.toJson(null);
        System.out.println(json);
    }

控制台输出:

{"i":5}
f:Foo [s=null, i=5]
null

在biu~出来的效果

public static void main(String[] args) {
        // TODO Auto-generated method stub
        Gson gson = new GsonBuilder().serializeNulls().create();
        Foo foo = new Foo();
        String json = gson.toJson(foo);
        System.out.println(json);
        Foo f = gson.fromJson(json, Foo.class);
        System.out.println("f:"+f);
        json = gson.toJson(null);
        System.out.println(json);
    }

控制台输出:

{"s":null,"i":5}
f:Foo [s=null, i=5]
null

看出二者的区别了吧,当使用biu~方式时属性为空的时候输出来的json字符串是有键值key的,而直接new出来的就没有。

非常感谢看到这里的朋友,最后送点一个非常实用的工具给你
这个工具叫做json实体转换器,用法很简单,我直接贴图就好了。
这里写图片描述
确认提交之后将自动生成相应的实体
这里写图片描述
看看生成的实体张什么样子吧

工具下载地址:http://download.csdn.net/detail/u013922681/9468715

package domain;

import java.lang.reflect.Field;
import java.io.Serializable;
import java.util.List;

public class JavaName implements Serializable {
    public String note;
    public int errCode;
    public BoyStudent boyStudent;

    public class BoyStudent implements Serializable {
        public String sex;
        public String intertests;
        public Student student;

        public class Student implements Serializable {
            public String birthDay;
            public String name;
            public int id;

            public void setBirthDay(String birthDay) {
                this.birthDay = birthDay;
            }

            public String getBirthDay() {
                return this.birthDay;
            }

            public void setName(String name) {
                this.name = name;
            }

            public String getName() {
                return this.name;
            }

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

            public int getId() {
                return this.id;
            }

            public String toString() {
                String s = "";
                Field[] arr = this.getClass().getFields();
                for (Field f : getClass().getFields()) {
                    try {
                        s += f.getName() + "=" + f.get(this) + "\n,";
                    } catch (Exception e) {
                    }
                }
                return getClass().getSimpleName()
                        + "["
                        + (arr.length == 0 ? s : s.substring(0, s.length() - 1))
                        + "]";
            }
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public String getSex() {
            return this.sex;
        }

        public void setIntertests(String intertests) {
            this.intertests = intertests;
        }

        public String getIntertests() {
            return this.intertests;
        }

        public String toString() {
            String s = "";
            Field[] arr = this.getClass().getFields();
            for (Field f : getClass().getFields()) {
                try {
                    s += f.getName() + "=" + f.get(this) + "\n,";
                } catch (Exception e) {
                }
            }
            return getClass().getSimpleName() + "["
                    + (arr.length == 0 ? s : s.substring(0, s.length() - 1))
                    + "]";
        }
    }

    public void setNote(String note) {
        this.note = note;
    }

    public String getNote() {
        return this.note;
    }

    public void setErrCode(int errCode) {
        this.errCode = errCode;
    }

    public int getErrCode() {
        return this.errCode;
    }

    public String toString() {
        String s = "";
        Field[] arr = this.getClass().getFields();
        for (Field f : getClass().getFields()) {
            try {
                s += f.getName() + "=" + f.get(this) + "\n,";
            } catch (Exception e) {
            }
        }
        return getClass().getSimpleName() + "["
                + (arr.length == 0 ? s : s.substring(0, s.length() - 1)) + "]";
    }
}

好了,第一次写这么认真~觉得可以的话点个赞!
对了,能看官网的demo就看官网的吧!
链接如下:https://sites.google.com/site/gson/gson-user-guide#TOC-Gson-Users

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值