一、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来进行序列化和反序列化(会稍微耗性能)