Android序列化方案之JSON

一、JSON是什么?

1、定义:JSON全称(JavaScript Object Notation:javaScript的对象表示法),是一种轻量级的数据交换格式。

2、作用:数据标记、存储&传输。

3、特点:读写速度快、解析简单、轻量级、独立于语言和开发平台。

4、序列化:前面两篇文章讲的是狭义上的对象序列化:serializable(基于反射机制,适合数据IO磁盘操作和网络传输)、Parcelable(基于IBinder,适合内存的进程间数据传递);而JSON称为广义上的序列化,一种序列化的拓展:数据序列化

二、JSON格式语法?

1、实例:1个JSON文件里含多个数据,这些数据 以 JSON值 的形式存在

{
    "name": "OrgJson",
    "sex": "男",
    "age": "23",
    "courses": [
        {
            "name": "语文",
            "score": 98
        },
        {
            "name": "数学",
            "score": 100
        }
    ]
}

2、说明:一个JSON值的内容形式可以是:”名称 - 值“对数组 对象,下面将详细说明

三、JSON的解析方式有哪几种?

1、Android studio自带的org.json解析方式

解析原理:基于文档驱动

解析流程:把全部文件读入到内存中 ->> 遍历所有数据 ->> 根据需要检索想要的数据

代码实战:手动生成一个JSON数据,在手动解析JSON数据。(org.json:优点是自带的,不用引入依赖,体积小。不足的是没有一个将JSONObject对象直接转JavaBean的方法)

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            createJson();//生成JSON数据,保存在手机目录
        } catch (JSONException | IOException e) {
            e.printStackTrace();
        }
        try {
            parseJson();//解析JSON数据
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }
    }

    private void createJson() throws JSONException, IOException {
        File file = new File(getFilesDir(), "test.json");
        //实例化一个JSONObject对象
        JSONObject student = new JSONObject();
        student.put("name", "OrgJson");
        student.put("sex", "男");
        student.put("age", "23");
        JSONObject course1 = new JSONObject();
        course1.put("name", "语文");
        course1.put("score", 98);
        JSONObject course2 = new JSONObject();
        course2.put("name", "数学");
        course2.put("score", 100);
        //实例化一个JSON数组
        JSONArray cources = new JSONArray();
        //将course1添加到JSONArray,下标为0
        cources.put(0, course1);
        cources.put(1, course2);
        student.put("courses", cources);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(student.toString().getBytes());
        fos.close();
        Log.i("Main", "json:" + student.toString());
    }

    private void parseJson() throws IOException, JSONException {
        File file = new File(getFilesDir(), "test.json");
        FileInputStream fis = new FileInputStream(file);
        InputStreamReader inputStreamReader = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(inputStreamReader);
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        while (null != (line = br.readLine())) {
            stringBuilder.append(line);
        }
        fis.close();
        inputStreamReader.close();
        br.close();
        Log.i("Main", "name:" + stringBuilder.toString());

        Student student = new Student();
        JSONObject jsonObject = new JSONObject(stringBuilder.toString());
        String name = jsonObject.optString("hobby");
//        String name1 = jsonObject.getString("hobby");
        //optString当json中没对应的key时,返回"",而getString会抛出异常
        Log.i("Main", "name:" + name.length());

        student.setName(jsonObject.optString("name",""));
        student.setSex(jsonObject.optString("sex",""));
        student.setAge(jsonObject.optString("age",""));

        JSONArray jsonArray = jsonObject.optJSONArray("courses");
        List<Student.CoursesBean> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.length(); i++) {
            Student.CoursesBean bean = new Student.CoursesBean();
            JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
            bean.setName(jsonObject1.optString("name"));
            bean.setScore(jsonObject1.optInt("score"));
            list.add(bean);
        }
        student.setCourses(list);
        Log.i("Main","parseJson " + student.toString());
    }
}
public class Student {
    /**
     * name : OrgJson
     * sex : 男
     * age : 23
     * courses : [{"name":"语文","score":98},{"name":"数学","score":100}]
     */
    private String name;
    private String sex;
    private String age;
    private List<CoursesBean> courses;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public List<CoursesBean> getCourses() {
        return courses;
    }
    public void setCourses(List<CoursesBean> courses) {
        this.courses = courses;
    }
    public static class CoursesBean {
        /**
         * name : 语文
         * score : 98
         */
        private String name;
        private int score;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getScore() {
            return score;
        }
        public void setScore(int score) {
            this.score = score;
        }
        @Override
        public String toString() {
            return "CoursesBean{" +
                    "name='" + name + '\'' +
                    ", score=" + score +
                    '}';
        }
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age='" + age + '\'' +
                ", courses=" + courses +
                '}';
    }
}

2、Gson解析

解析原理:基于事件驱动

解析流程:根据所需取的数据 建立1个对应于JSON数据的JavaBean类,即可通过简单操作解析出所需数据

具体使用:需要引入依赖库(2020.11.29的最新版本):

步骤一:引入最新Gson依赖库

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

步骤二:创建javaBean,一个与JSON数据对应的大的JavaBean类(可能内部有多个嵌套的JavaBean)

1、创建规则:

什么意思呢上面的规则,就是说如何根据JSON数据来生成一个JavaBean呢?其实已经有Android studio的插件来自动生成了:GsonFormat插件

2、GsonFormat插件的安装以及使用:

使用:新建一个User的JavaBean类:我的快捷键Alt+N出来个弹框,点击GsonFormat

这样一个JavaBean就生成好了。如下,然后我们在解释一下上面的这个规则:

注意:变量需要和上面的key对应上,你不想要解析的字段可以不用写进JavaBean中。一个{}就是一个Object:最外层的{}就是User这个JavaBean,里面还有嵌套的{"name":"语文","score":98}对应的是CoursesBean这个JavaBean。一个[]就对应一个数组。

package com.fengshows.day11_json.gsonTest;

import java.util.List;

/**
 * Date: 2020/11/29
 * Author: SunBinKang
 * Description:
 */
public class User {
    /**
     * name : OrgJson
     * sex : 男
     * age : 23
     * translation : ["车","船"]
     * courses : [{"name":"语文","score":98},{"name":"数学","score":100}]
     */
    private String name;
    private String sex;
    private int age;
    private List<String> translation;
    private List<CoursesBean> courses;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public List<String> getTranslation() {
        return translation;
    }
    public void setTranslation(List<String> translation) {
        this.translation = translation;
    }
    public List<CoursesBean> getCourses() {
        return courses;
    }
    public void setCourses(List<CoursesBean> courses) {
        this.courses = courses;
    }
    public static class CoursesBean {
        /**
         * name : 语文
         * score : 98
         */
        private String name;
        private int score;

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getScore() {
            return score;
        }
        public void setScore(int score) {
            this.score = score;
        }
    }
}

3、Gson如何序列化和反序列化呢?

序列化:将JavaBean对象转成json字符串。

反序列化:将json字符串转成JavaBean。

简单代码演示:新建一个简单的GsonBean类:

public class GsonBean {
    public int age;
    public String name;
    @Override
    public String toString() {
        return "GsonBean{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public class GsonTest {
    public static void main(String[] args) {
        Gson gson = new Gson();
        GsonBean gsonBean = new GsonBean();
        gsonBean.age= 2;
        gsonBean.name = "str";
        //序列化:将gsonBean对象转成json字符串了
        String json = gson.toJson(gsonBean);
        System.out.println("json: " + json);
        //反序列化:将json字符串对象转成GsonBean了
        GsonBean gsonBean1 = gson.fromJson(json,GsonBean.class);
        System.out.println("gsonBean1: " + gsonBean1.toString());
    }
}

执行结果:

三、Gson解析的拓展知识

1、几个常用的注解

@SerializedName("name1"):对象序列化成json字符串的时候修改名字

    public int age;
    @SerializedName("name1")
    public String name;//给name字段加上了SerializedName注解

序列化结果:

@Since(1.0)/@Until(1.0)版本控制的作用,>=和<=才参与序列化

Gson gson = new GsonBuilder().setVersion(1.2).create();//可以这样创建Gson来设置当前解析的版本

2、自定义TypeAdapter解析数据。(两个关键的类JsonWriter和JsonReader)

public class GsonBeanAdapter extends TypeAdapter<GsonBean> {
    @Override
    public void write(JsonWriter out, GsonBean value) throws IOException {//将GsonBean对象解析为字符串
        if (value == null) {//进行非空判断
            out.nullValue();
            return;
        }
        out.beginObject();
        out.name("name").value(value.name);
        out.name("age").value(value.age);
        out.endObject();
    }

    @Override
    public GsonBean read(JsonReader in) throws IOException {//将字符串转为JavaBean对象
        if (in.peek() == JsonToken.NULL) {//进行非空判断
            in.nextNull();
            return null;
        }
        GsonBean gsonBean = new GsonBean();
        in.beginObject();
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "name":
                    gsonBean.name = in.nextString();
                    break;
                case "age":
                    gsonBean.age = in.nextInt();
                    break;
            }
        }
        in.endObject();
        return gsonBean;
    }
}

这样就会使用我们自定义的TypeAdapter来进行序列化和反序列化。如果没有设置,Gson源码就会使用反射的TypeAdapter来进行序列化和反序列化(会稍微耗性能)

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页