irpas技术客

Android之JSON与泛型_Jackygod66_android gson 泛型

irpas 4175

学习目标 一、对给定的几种有共同特性的JSON数据抽象出泛型基类及实体类,并使用JSON数据解析库(Jackson、Gson、FastJSON),把对象序列化为JSON字符串,以及把JSON字符串反序列化为类对象。本人在这篇文章中使用的是GSON解析库。 扩展学习:了解Jackson、Gson、FastJSON这三种JSON解析库,分析三者的优缺点。

首先先将GSON包导入到项目中的lib文件夹,我用的是GSON.2.8.5版本,当然也可通过在gradle文件里添加依赖,

implementation 'com.google.code.gson:gson:2.8.5' 一、根据给出的数据格式编写简单实体类,给出实体类的代码以及相关的序列化和反序列化代码。 { "code": 1, "data": { "describe": "example data", "stringList": [ "zhangsan", "lisi", "wangwu" ], "objArray": [ { "name": "张三", "addr": "xxx街道" }, { "name": "李四", "addr": "y市" } ] } } 1.编写一个简易的界面,用LinearLayout布局,自上而下三个控件,EditText编辑文本框,Button按钮,TextView文字显示框 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="100dp" android:id="@+id/inputText"/> <Button android:layout_width="100dp" android:layout_height="40dp" android:id="@+id/button_1" android:onClick="button_1_onClick" android:layout_marginTop="30dp" android:layout_marginLeft="20dp" android:text="反序列化"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:text="输出框" android:id="@+id/text" android:textSize="15dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> 2.根据JSON数据编写对应的类SimpleJSON,同时SimpleJSON的属性包含一个Data对象,一层一层定义,以此类推,建立Data类,Name类...... //编写JSON格式对应的简单实体类 public class SimpleJSON { private int code; private Data data; @Override public String toString() { return "SimpleJSON{" + "code=" + code + ", data=" + data.toString() + '}'; } //默认构造方法 public SimpleJSON(){} public int getCode() { return code; } public void setCode(int code) { this.code = code; } public Data getData() { return data; } public void setData(Data data) { this.data = data; } } import java.util.ArrayList; //SimpleJSON中的data对象类 public class Data { private String describe; private ArrayList<String> stringList; private ArrayList<Name> objArray; @Override public String toString() { return "Data{" + "describe='" + describe + '\'' + ", stringList=" + stringList + ", objArray=" + objArray + '}'; } public String getDescribe() { return describe; } public void setDescribe(String describe) { this.describe = describe; } public ArrayList<String> getStringList() { return stringList; } public void setStringList(ArrayList<String> stringList) { this.stringList = stringList; } public ArrayList<Name> getObjArray() { return objArray; } public void setObjArray(ArrayList<Name> objArray) { this.objArray = objArray; } } //objArray中的Name对象类 public class Name { private String name; private String addr; @Override public String toString() { return "Name{" + "name='" + name + '\'' + ", addr='" + addr + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } } 3.编写一个利用GSON解析库解析JSON数据的工具类,采用GSON的两种做法

1.利用GSON官方文档中的按层解析法,逐步解析

import com.google.gson.stream.JsonReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; public class Test { public String set(String str) throws IOException { //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); JsonReader jsonReader = new JsonReader(in); SimpleJSON simpleJSON = readSimpleJSON(jsonReader); return simpleJSON.toString(); } public Test(){} //读取简单实体类 private SimpleJSON readSimpleJSON(JsonReader jsonReader) throws IOException { SimpleJSON simpleJSON = new SimpleJSON(); //读取对象用下面这种方法 jsonReader.beginObject(); //判断指针是否到尾 while(jsonReader.hasNext()){ String str = jsonReader.nextName(); if("code".equals(str)){ simpleJSON.setCode(jsonReader.nextInt()); } else if("data".equals(str)){ simpleJSON.setData(readData(jsonReader)); } //跳过这次判断,即特殊情况为空时,不做任何处理,直接返回空值 else jsonReader.skipValue(); } jsonReader.endObject(); return simpleJSON; } //读取SimpleJSON实体类内部的封装数据实体类data private Data readData(JsonReader jsonReader) throws IOException { Data data = new Data(); jsonReader.beginObject(); while(jsonReader.hasNext()){ String str = jsonReader.nextName(); if("describe".equals(str)){ data.setDescribe(jsonReader.nextString()); } else if("stringList".equals(str)){ data.setStringList(readStringList(jsonReader)); } else if("objArray".equals(str)){ data.setObjArray(readObjArray(jsonReader)); } else jsonReader.skipValue(); } jsonReader.endObject(); return data; } //读取内部数组类型objArray,读取数组类型用以下方法 private ArrayList<Name> readObjArray(JsonReader jsonReader) throws IOException { ArrayList<Name> list = new ArrayList<>(); jsonReader.beginArray(); while(jsonReader.hasNext()){ list.add(readName(jsonReader)); } jsonReader.endArray(); return list; } //读取数组中的对象Name private Name readName(JsonReader jsonReader) throws IOException { Name name = new Name(); jsonReader.beginObject(); while(jsonReader.hasNext()){ String str = jsonReader.nextName(); if("name".equals(str)){ name.setName(jsonReader.nextString()); } else if("addr".equals(str)){ name.setAddr(jsonReader.nextString()); } else jsonReader.skipValue(); } jsonReader.endObject(); return name; } //读取stringArray类型数组 private ArrayList<String> readStringList(JsonReader jsonReader) throws IOException { ArrayList<String> list = new ArrayList<>(); jsonReader.beginArray(); while(jsonReader.hasNext()){ list.add(jsonReader.nextString()); } jsonReader.endArray(); return list; } }

2.利用GSON自带的解析方法,快速解析

//将JSON数据反序列化为Java类对象简单方法,此方法解析时,一定要将此部分放入try-catch语句中,不然会因为数据格式不正确而导致闪退 Gson gson = new Gson(); SimpleJSON obj= gson.fromJson(in,SimpleJSON.class);

3.序列化操作,为了方便演示,即采用上述第 3.1 步反序列化的出来的对象

//将对象序列化为JSON数据 Gson gson = new Gson(); String json = gson.toJson(simpleJSON); System.out.println(json);

4.在MainActivity中进行控件初始化,并测试JSON数据是否解析成功

import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.io.IOException; public class MainActivity extends AppCompatActivity { //声明所有控件 private TextView textView; private Button button_1; private EditText inputText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化 init(); } //初始化绑定控件 public void init(){ textView = findViewById(R.id.text); button_1 = findViewById(R.id.button_1); inputText = findViewById(R.id.inputText); } //绑定简单实体类点击事件 public void button_1_onClick(View view) { String str = inputText.getText().toString(); Test test = new Test(); try { textView.setText(test.set(str)); } catch (IOException e) { textView.setText("JSON格式不正确"); } } }

5.执行结果

二、带泛型的实体类,事实上需要写4个实体类,一个最外层定义泛型的类如BaseData,以及3个具体的数据实体类Data1 Data2 Data3 //这是三个JSON数据,不是一个,输入时分开输入 { "errorCode": 0, "obj": { "user": "admin", "attr": { "prefix": "start-", "suffix": ".jpg" } } } { "errorCode": 0, "obj": { "name": "cat", "style": { "width": 1920, "height": 1080 } } } { "errorCode": 0, "obj": "hello" } 1.添加一个按钮控件,同时将按钮控件都放在一个LinearLayout内部实现水平布局 <Button android:id="@+id/button_2" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_marginLeft="5dp" android:layout_marginTop="30dp" android:onClick="button_2_onClick" android:text="泛型反序列化" /> 2.根据对应实体类,编写相应的泛型内和实体类,即GenericsJSON基类,和Obj1,Obj2,Obj3数据实体类,因为Obj3的数据类型为String,故不用实现Obj3数据类 //基类 public class GenericsJSON<T> { private int errorCode; T obj; @Override public String toString() { return "GenericsJSON{" + "errorCode=" + errorCode + ", obj=" + obj.toString() + '}'; } GenericsJSON(){} public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } //Obj1数据类 public class Obj1 { private String user; private Attr attr; @Override public String toString() { return "Obj1{" + "user='" + user + '\'' + ", attr=" + attr + '}'; } Obj1(){} public String getUser() { return user; } public void setUser(String user) { this.user = user; } public Attr getAttr() { return attr; } public void setAttr(Attr attr) { this.attr = attr; } public class Attr{ private String prefix; private String suffix; Attr(){} public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return suffix; } public void setSuffix(String suffix) { this.suffix = suffix; } } } //Obj2数据类 public class Obj2 { private String name; private Style style; Obj2(){} @Override public String toString() { return "Obj2{" + "name='" + name + '\'' + ", style=" + style + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Style getStyle() { return style; } public void setStyle(Style style) { this.style = style; } public class Style{ private int width; private int hight; Style(){} public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHight() { return hight; } public void setHight(int hight) { this.hight = hight; } } } 3.编写工具类Test1 import com.google.gson.Gson; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; public class Test1{ public String set1(String str) { //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); try{ //将JSON数据反序列化为Java类对象简单方法 Gson gson = new Gson(); GenericsJSON<Obj1> obj1 = gson.fromJson(in, GenericsJSON.class); //将对象序列化为JSON数据 Gson gson1 = new Gson(); String json = gson1.toJson(obj1); System.out.println(json); return obj1.toString(); }catch(Exception e){ return "JSON数据格式不正确"; } } public String set2(String str) { //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); try{ //将JSON数据反序列化为Java类对象简单方法 Gson gson = new Gson(); GenericsJSON<Obj2> obj2 = gson.fromJson(in, GenericsJSON.class); //将对象序列化为JSON数据 Gson gson1 = new Gson(); String json = gson1.toJson(obj2); System.out.println(json); return obj2.toString(); }catch(Exception e){ return "JSON数据格式不正确"; } } public String set3(String str) { //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); try{ //将JSON数据反序列化为Java类对象简单方法 Gson gson = new Gson(); GenericsJSON<String> obj3 = gson.fromJson(in, GenericsJSON.class); //将对象序列化为JSON数据 Gson gson1 = new Gson(); String json = gson1.toJson(obj3); System.out.println(json); return obj3.toString(); }catch(Exception e){ return "JSON数据格式不正确"; } } } 4.实现按钮控件事件,这里为了省去麻烦,同一个按钮分别测试三次不同类型的JSON数据 public void button_2_onClick(View view) { String str = inputText.getText().toString(); //第一个JSON格式 Test1 test1 = new Test1(); textView.setText(test1.set1(str)); // // //第二个JSON格式 // Test1 test2 = new Test1(); // textView.setText(test2.set2(str)); // // //第三个JSON格式 // Test1 test3 = new Test1(); // textView.setText(test3.set3(str)); } 5.执行结果

三、自定义反序列化,要求使用接口或基类定义datas列表里的数据类型,然后自定义反序列化,根据typeCode反序列化为不同的实现类 { "datas": [ { "typeCode": 1, "typeName": "type1", "attr": { "prefix": "fff", "suffix": "xsss" }, "msg":"hello" }, { "typeCode": 2, "typeName": "type2", "style": { "size": 12, "color": "#FF5A207E" }, "text": "thanks" } ] } 1.添加一个按钮控件 <Button android:id="@+id/button_3" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_marginLeft="5dp" android:layout_marginTop="30dp" android:onClick="button_3_onClick" android:text="自定义反序列化" /> 2.根据JSON格式实现对象类,这个地方的类定义和相互之间的关系很重要,首先是datas类型的数组类,里面包括着一个DataType父类,只有一个属性typeCode,接着实现两个子类Data1,Data2继承DataType import java.util.ArrayList; import java.util.List; //JSON中的datas数组类 public class Datas { //定义一个DataType类型数组 private List<DataType> datas; @Override public String toString() { return "Datas{" + "datas=" + datas + '}'; } public Datas(){ datas = new ArrayList<>(); } public List<DataType> getList() { return datas; } public void setList(List<DataType> datas) { this.datas = datas; } } //父类DataType,只有一个属性typeCode,其他的属性在子类里声明 public class DataType { private int typeCode; @Override public String toString() { return "DataType{" + "typeCode=" + typeCode + '}'; } public int getTypeCode() { return typeCode; } public void setTypeCode(int typeCode) { this.typeCode = typeCode; } DataType(){} } //typeCode为1的子类 public class Data1 extends DataType{ private String typeName; private Attr attr; private String msg; @Override public String toString() { return "Data1{" + "typeName='" + typeName + '\'' + ", attr=" + attr + ", msg='" + msg + '\'' + '}'; } Data1(){} public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } public Attr getAttr() { return attr; } public void setAttr(Attr attr) { this.attr = attr; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } //内部的Attr对象类 public class Attr{ private String prefix; private String suffix; @Override public String toString() { return "Attr{" + "prefix='" + prefix + '\'' + ", suffix='" + suffix + '\'' + '}'; } Attr(){} public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return suffix; } public void setSuffix(String suffix) { this.suffix = suffix; } } } //typeCode为2的子类 public class Data2 extends DataType{ private String typeName; private Style style; private String text; Data2(){} @Override public String toString() { return "Data2{" + "typeName='" + typeName + '\'' + ", style=" + style + ", text='" + text + '\'' + '}'; } public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } public Style getStyle() { return style; } public void setStyle(Style style) { this.style = style; } public String getText() { return text; } public void setText(String text) { this.text = text; } //内部style类对象 public class Style{ private int size; private String color; @Override public String toString() { return "Style{" + "size=" + size + ", color='" + color + '\'' + '}'; } Style(){} public int getSize() { return size; } public void setSize(int size) { this.size = size; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } } 3.根据需要,实现自定义反序列化方法DataDeserializer类 import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializer; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; public class Test2 { public String set(String str){ //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); try{ //注册自定义反序列化方法 GsonBuilder gsonBuilder = new GsonBuilder(); JsonDeserializer<DataType> deserializer = new DataDeserializer(); gsonBuilder.registerTypeAdapter(DataType.class,deserializer); Gson gson = gsonBuilder.create(); //实现自定义反序列化 Datas list = gson.fromJson(in, Datas.class); //将对象序列化为JSON数据 Gson gson1 = new Gson(); String json = gson1.toJson(list); System.out.println(json); return list.toString(); }catch(Exception e){ return "JSON数据格式不正确"; } } } 4.编写JSON解析操作类Test2 import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; public class Test2 { public String set(String str){ //读取字符串转化为输入流再转化为JsonReader InputStream is = new ByteArrayInputStream(str.getBytes()); InputStreamReader in = new InputStreamReader(is); try{ //注册自定义反序列化方法 Gson gson = new GsonBuilder().serializeNulls().create(); //实现自定义反序列化 Datas list = gson.fromJson(in, Datas.class); //将对象序列化为JSON数据 Gson gson1 = new Gson(); String json = gson1.toJson(list); System.out.println(json); return list.toString(); }catch(Exception e){ return "JSON数据格式不正确"; } } } 5.编写按钮事件 public void button_3_onClick(View view) { String str = inputText.getText().toString(); Test2 test = new Test2(); textView.setText(test.set(str)); } 6.执行结果

?

扩展学习:了解Jackson、Gson、FastJSON这三种JSON解析库,分析三者的优缺点。 因为我还未使用过Jackson和FastJSON解析库,所以我上网查阅了资料,大部分数据都显示,若是解析少量的JSON数据,GSON的效率相对而言效果较好,FastJSON也不错,但如果是十分大量的数据,Jackson解析库就显现出了其优势。FastJSON设计的初衷就是为了解析快,所以重点都放在了“快”,但“功能性”相比Jaskson而言就自愧不如了,所以说,如果作为SpringBoot技术栈开发的话, 用默认的Jackson是再好不过了,现在的项目开发也大多数是使用Jackson。

作者有道云原文链接:

https://note.youdao.com/s/JLzf9n2Ihttps://note.youdao.com/s/JLzf9n2I


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Android #gson #泛型