android json 教程 pdf,Android下的Json学习指南

本文详细介绍了JSON的基本概念、语法及在Android中的解析方式,包括使用Android自带的JSONObject和JSONArray,以及使用JsonReader进行流式处理。此外,还深入探讨了Gson库的使用,包括反序列化、泛型处理、注解功能以及各种配置选项,展示了Gson在处理复杂JSON数据时的强大能力。
摘要由CSDN通过智能技术生成

Json基础知识

Json是什么

Json是JavaScript Object Notation(JavaScript对象表示法)的缩写,是一种轻量级的文本数据交换格式,是用来存储和交换文本信息的语法。

它独立于语言且具有自我描述性,更容易理解。虽然使用Javascript语法来描述数据对象,但很多编程语言都支持Json。

Json的文件类型是".json",MIME类型是"application/json"。

Json的语法

典型的Json实例:

{ "photos": { "page": 1, "pages": 10, "perpage": 100, "total": "1000",

"photo": [

{ "id": "31624984467"}, {"owner": "155140314@N03"}, {"secret": "efa8606dc9"}]}}

Json语法是JS语法的子集:

数据在名称/值对{ key:value }中

数据由逗号分隔

大括号保存对象

中括号保存数组

Json的key为字符串,值可以是:

数字(整数或浮点数)

字符串(在双引号中)

逻辑值(true 或 false)

数组(在中括号中)

对象(在大括号中)

null

Json对象

JSON 对象在大括号({ })中书写,对象可以包含多个名称/值对。名称/值对中使用冒号(:)分割,每个名称/值对对使用逗号(,)分割。

一个典型的例子:

{"id": "31624984467"}

Json数组

JSON 数组在中括号中书写,数组可包含多个对象,也可只是合法的基本数据类型:

[{ "id": "31624984467"},{ "owner": "155140314@N03"}]

["a","b","c"]

Android中的Json解析

利用Android自带的Json解析类

使用JSONObject,JSONArray来解析:

JSONObject类:生成Json对象,可以完成Json字符串与Java对象的相互转换。

JSONArray类:生成Json数组,可以完成Json字符串与Java集合或对象的相互转换。

JSONStringer类:Json文本构建类,这个类可以帮助快速和便捷的创建JSON text, 每个JSONStringer实体只能对应创建一个JSON text。

JSONException类:Json异常。

使用步骤介绍:

获取Json字符串。一般是从网络获取,为了方便这里直接从本地获取。

使用JSONObject类,利用Json字符串生成JSONObject对象。

使用getJSONObject,getJSONArray等方法一个个的将Json字符串分解,再从中抠出所需要的属性。

举个栗子:

josn数据为:

{ "photos": { "page": 1, "pages": 10, "perpage": 100, "total": "1000",

"photo": [

{ "id": "31624984467", "owner": "155140314@N03","title": "Happy New Year 2019 : Happy New Year Happy New Year 2019", "url_s": "https:\/\/farm5.staticflickr.com\/4852\/31624984467_efa8606dc9_m.jpg"},

{ "id": "31624992207", "owner": "163032290@N04","title": "","url_s": "https:\/\/farm5.staticflickr.com\/4844\/31624992207_a3196f29b6_m.jpg"},

{ "id": "31624994507", "owner": "146047562@N03","title": "swt33.c33.kr정품비아그라구입방법카톡:swt33텔레:swt33비아그라구입처,비아그라구입정보,클럽비아그라판매처,비아그라구입사이트,강력비아그라효능","url_s": "https:\/\/farm5.staticflickr.com\/4819\/31624994507_0a022a924c_m.jpg"}]}

从资源目录中获取json数据

private String jsonFromLocal() throws IOException {

InputStream inStr = getResources().openRawResource(R.raw.jsontest);

InputStreamReader inReader = new InputStreamReader(inStr);

BufferedReader bufferedReader = new BufferedReader(inReader);

StringBuilder builder = new StringBuilder(" ");

String str = null;

while ((str = bufferedReader.readLine()) != null) {

builder.append(str);

builder.append("\n");

}

inReader.close();

bufferedReader.close();

return builder.toString();

}

接着就开始扣需要的属性了。

//生成JSONObject对象

String json = jsonFromLocal();

JSONObject jsonBody = new JSONObject(json);

parseItem(items, jsonBody);`

private void parseItem(List items, JSONObject jsonBody) throws JSONException {//先获取最外层的对象photos

JSONObject photosJsonObject = jsonBody.getJSONObject("photos");

//再获取photos内的对象数组photo

JSONArray photoJsonArray = photosJsonObject.getJSONArray("photo");

for (int i = 0; i < 3; i++) {

//再依据具体的key来获取需要的属性

JSONObject photoJsonObject = photoJsonArray.getJSONObject(i);

Item item = new Item();

item.setId(photoJsonObject.getString("id"));

item.setCaption(photoJsonObject.getString("title"));

item.setUrl(photoJsonObject.getString("url_s"));

item.setOwner(photoJsonObject.getString("owner"));

items.add(item);

}

}

item类:

public class Item {

private String id;

private String url;

private String owner;

private String caption;

......(get,set等方法)

使用JsonReader来解析

这种方式有点类似XML文档的解析,使用深度优先遍历,寻找到需要的标记然后消耗掉它。对象的解析从beginObject()开始,到endObject()结束。数组的解析从beginArray()开始,到endArray()结束。

下面我们来看一看吧,json数据依旧是之前的!

JsonReader reader = new JsonReader(new StringReader(json));//获取reader对象

try {

reader.beginObject();//从Json流中消耗一个标记,开始解析对象

while (reader.hasNext()) {//循环判断当前数组或者对象是否有下一个元素

String propertyName = reader.nextName();//获取key值

if (propertyName.equals("photos")) {

readPhotos(reader, items);

} else {

reader.skipValue();//跳过下一个不需要的元素

}

}

reader.endObject();//结束对象解析

} finally {

reader.close();

}

}

private void readPhotos(JsonReader reader, List items) throws IOException {

reader.beginObject();

while (reader.hasNext()) {

String propertyName = reader.nextName();

if (propertyName.equals("photo")) {

readPhoto(reader, items);

} else {

reader.skipValue();

}

}

reader.endObject();

}

private void readPhoto(JsonReader reader, List items) throws IOException {

reader.beginArray();//开始数组解析

String id = null,url_s = null,owner = null,title = null;

while (reader.hasNext()) {

PhotoItem item = new PhotoItem();

reader.beginObject();

while (reader.hasNext()) {

String propertyName = reader.nextName();

switch (propertyName) {

case "id":

id = reader.nextString();//获取"id"的值,返回String类型

break;

case "url_s":

url_s = reader.nextString();

break;

case "owner":

owner = reader.nextString();

break;

case "title":

title = reader.nextString();

break;

default:

reader.skipValue();

break;

}

}

item.setId(id);

item.setUrl(url_s);

item.setOwner(owner);

item.setCaption(title);

items.add(item);

reader.endObject();

}

reader.endArray();//结束数组解析

}`

注意:

如果使用了nextName(),而没有使用next **()( **可以是String,Int,Long等)方法或者skipValue(),这时候就会触发异常,这一组方法需要配套使用。同理使用了beginObject()就要使用endObject()结尾,使用了beginArray()就要使用endArray()结尾。

开源库Gson使用

尝试完了繁琐的Android自带的Json解析类,现在就来看看第三方开源库Gson的威力吧!

导入依赖

dependencies { implementation 'com.google.code.gson:gson:2.8.5' }

Gson的基本使用

Gson对象的创建

有两种方式来创建Gson对象。

第一种是直接new一个对象: Gson gson = new Gson();

第二种是利用GsonBuilder来创建,可以进行多项配置:Gson gson = new GsonBuilder().create();

Gson的反序列化

Gson最为重要的两个方法分别是toJson()和fromJson()。toJson()用来序列化,fromJson()用来反序列化。

1 简单Json数组解析:

Json数据:

[ "Happy New Year 2019 : Happy New Year Happy New Year 2019",

"Karma's black iron prison",

"Hong Kong gov't bid to redevelop Fanling course 'absurd' says golf alliance convener"

]

Json数组转化为字符串数组:

Gson gson = new Gson();

String json_t2 = null;

try {

json_t2 = jsonFromLocal(R.raw.json_t2);

} catch (IOException e) {

e.printStackTrace();

}

String[] strings = gson.fromJson(json_t2, String[].class);

for (String st : list) {

Log.i(TAG, st);

}

Json数组转化为字符串List:

Gson gson = new Gson();

String json_t2 = null;

try {

json_t1 = jsonFromLocal(R.raw.json_t2);

} catch (IOException e) {

e.printStackTrace();

}

List list = gson.fromJson(json_t2,new TypeToken>(){}.getType());

for (String st : list) {

Log.i(TAG, st);

}

Gson中的泛型表示:

在解析Json数组时,一般使用两种方法,一个是数组,一个是List。而因为List对于增删操作比较方便,一般选用List。

但对于List来说,上面代码中的 String[].class ,不能直接改为List.class。因为对于Java来说 List 和List这两个字节码文件只有一个,就是 List.class,这就是Java泛型使用时要注意的泛型擦除问题。

为了解决上述问题,Gson提供TypeToken来实现对泛型的支持。TypeToken 这个类帮助我们捕获(capture)像 List 这样的泛型信息。Java编译器会把捕获到的泛型信息编译到这个匿名内部类里,然后在运行时就可以被getType()方法用反射的 API 提取到。也就是将泛型T转成 .class

2 稍复杂Json数据解析:

Json数据,目的是为了拿到totol数据:

{

"photo": [

{

"page": 1,

"pages": 10,

"perpage": 100,

"total": "1000"

},

{

"page": 2,

"pages": 20,

"perpage": 200,

"total": "1000"

},

{

"page": 3,

"pages": 30,

"perpage": 300,

"total": "1000"

}

]

}

第一步:根据Json数据建立简单Java类。可以使用Android Studio平台中的GsonFormat插件来快速构建。

public class JsonT1 {

public List photo;

public static class PhotoBean {

/**

* page : 1

* pages : 10

* perpage : 100

* total : 1000

*/

public int page;

public int pages;

public int perpage;

public String total;

}

}

第二步:解析Json数据。这里有两种方式,第一种是利用JsonParse类解析,有点类似于Android自带的JsonObject和JsonArray解析方式,得要扣需要的key。下面来看一下实现代码。

JsonObject jsonObject = new JsonParser().parse(json_t1).getAsJsonObject();

JsonArray jsonArray = jsonObject.getAsJsonArray("photo");

List jsonT1List = new ArrayList<>();

for (JsonElement element : jsonArray) {

JsonT1.PhotoBean jsonT1 = gson.fromJson(element, new TypeToken() {

}.getType());

jsonT1List.add(jsonT1);

}

Log.i(TAG, jsonT1List.get(0).total);

第二种是直接将Json数据解析为类对象,在得到对象之后再从对象内取出需要的List。

JsonT1 t1 = gson.fromJson(json_t1, JsonT1.class);

List photoBeanList = t1.photo;

Log.i(TAG,photoBeanList.get(0).total);

比较而言第二种方式更简洁一点,而且遇到更复杂一点的Json数据也可以使用。

3复杂Json数据解析

当遇到这种Json数据时:

{

"photos": {

"page": 1,

"pages": 10,

"perpage": 100,

"total": "1000",

"photo": [

{

"id": "31624984467",

"owner": "155140314@N03",

"secret": "efa8606dc9",

"server": "4852",

"farm": 5,

"title": "Happy New Year 2019 : Happy New Year Happy New Year 2019",

"ispublic": 1,

"isfriend": 0,

"isfamily": 0,

"url_s": "https:\/\/farm5.staticflickr.com\/4852\/31624984467_efa8606dc9_m.jpg",

"height_s": "240",

"width_s": "240"

},

{

"id": "31624992207",

"owner": "163032290@N04",

"secret": "a3196f29b6",

"server": "4844",

"farm": 5,

"title": "",

"ispublic": 1,

"isfriend": 0,

"isfamily": 0,

"url_s": "https:\/\/farm5.staticflickr.com\/4844\/31624992207_a3196f29b6_m.jpg",

"height_s": "135",

"width_s": "240"

},

"stat": "ok"

}

就到了JsonReader大显身手的地方了。使用这种流式处理方式再复杂的数据也能搞定。JsonReader是不是有点眼熟?没错,它和之前提到的Android自带的JsonReader处理方式几乎没有区别,连名字都一样。

018eff28ccd0?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

JsonReader.png

Gson注解

Gson的常用注解有@Expose,@SerializedName,@Since和@Until,@JsonAdapter。

1 @Expose注解

本注解用于指定某个属性是否进行序列化或反序列化,搭配GsonBuilder使用,源码如下。

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface Expose {

public boolean serialize() default true;

public boolean deserialize() default true;

}

包含两个属性serialize,deserialize。serialize 用于指定是否进行序列化,deserialize用于指定是否进行反序列化,默认为true。

举个栗子:

@Expose(serialize = false, deserialize = true)//可以反序列化,不可以序列化

public int page;

使用:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

2 @SerializedName注解

重命名指定的属性,源码如下。

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface SerializedName {

String value();

}

使用:

@SerializedName("pagesTotal")

public int pages;

3 @Since和@Until注解

和@Expose注解一样,用来指定某一属性是否可以序列化或反序列化。@Since 和 @Until 都包含一个 Double 属性值,用于设置版本号。Since 的意思是“自……开始”,Until 的意思是“到……为止”。当版本( GsonBuilder 设置的版本) 大于或等于 Since 属性值或小于 Until 属性值时字段会进行序列化和反序列化操作,而没有声明的字段都会加入序列化和反序列操作。

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.TYPE})

public @interface Until {

double value();

}

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.TYPE})

public @interface Since {

double value();

}

使用:

@Since(1.1)

public int perpage;

@Until(1.8)

public String total;

Gson gson = new GsonBuilder().setVersion(1.3).create();

4 @JsonAdapter注解

自定义序列化和反序列化,可以修饰类和字段。

首先需要自定义一个TypeAdapter的子类来接管目标类的序列化和反序列化过程,并且实现write和read方法。

public class SelfTypeAdapter extends TypeAdapter {

@Override

public void write(JsonWriter out, JsonT1 value) throws IOException {

}

@Override

public JsonT1 read(JsonReader in) throws IOException {

JsonT1 t1 = new JsonT1();

in.beginObject();

//.....解析操作

in.endObject();

return t1;

}

}

接着是注册自定义的SelfTypeAdapter类:

Gson gs = new GsonBuilder().registerTypeAdapter(JsonT1.class, new SelfTypeAdapter()).create();

其他Gson配置

1 格式化输出

Gson gson = new GsonBuilder()

.setPrettyPrinting()

.create();

2 日期时间格式化输出

Gson gson = new GsonBuilder()

.setPrettyPrinting()

.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//日期时间格式

3 Null值输出

Gson gson = new GsonBuilder()

.serializeNulls()

.create();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值