Android 网络数据JSON解析使用(建议收藏)

Posted 彬sir哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 网络数据JSON解析使用(建议收藏)相关的知识,希望对你有一定的参考价值。

(一)数据请求的准备和分析

这里使用的网络中请求的数据,相当于一个完整的app数据
这里推荐一个请求json数据的一个平台网站:showapi
必须先在平台注册账号,可以使用邮箱注册账号,注册账号后,可以兔费使用指定的一些接口,也可以付费使用一些付费接口
在showapi网址上输入“笑话大全”,按下图操作:





这代码中URL必须要添加showapi_appid和showapi_sign后才能在URL中请求到数据的
我们可以得到一个简单的URL字符串地址:http://route.showapi.com/341-1?showapi_appid=763801&time=&page=&maxResult=&showapi_sign=b60a1ce58a124536b5ff9eb33587c284点击这链接后显示json数据如下图:

对于这个返回的字符串我们也是要去看一下的,因为我们的json解析是从外到内一层一层去解析数据的。这里最好下载一个json数据格式化的工具,或者在网页中直接使用json格式工具,可以把一长串的字符串显示为json格式,方便我们去解析它的数据。
数据解析前,如图所示:

数据显示的是连接在一起的,很难区分标签和段落所以使用解析工具就非常重要了。
数据解析后,如图所示:

一、解析网络中复杂的json数据的程序示例

这里设计一个简易的笑话大全的软件
程序运行后显示的界面:

这里的布局设计的是两个按钮,单击“java请求”获取的是页面源码的json数据

点击“android请求笑话大全”,跳转到另一个页面显示解析后的数据

2.布局文件activity_main.xml的设计

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="conn1"
        android:text="java请求" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/main_et_pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_weight="1"
            android:background="@null"
            android:hint="输入页数"
            android:singleLine="true" />

        <CheckBox
            android:id="@+id/main_cb_isImage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择图片" />

    </LinearLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="conn2"
        android:text="Android请求笑话大全" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/main_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </ScrollView>

</LinearLayout>

上面使用一个ScrollView来显示获取到的json数据
3.布局文件activity_joke.xml的设计

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/joke_tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="title"
        android:textColor="@android:color/black"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/joke_tv_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="content"
        android:textColor="@android:color/black"
        android:textSize="16sp" />

    <ImageView
        android:id="@+id/joke_iv_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:adjustViewBounds="true"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/joke_tv_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:gravity="right"
        android:text="时间"
        android:textSize="14sp" />

</LinearLayout>

上面的布局是每一个笑话内容显示的布局设计
4.创建一个json解析和数据收集的类

package com.lwz.conn;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * 这是一个数据解析的工具类,
 * <p>
 * 这里是从源码中取出属性值
 * 这里是使用从外到内一层一层的去获取资源数据,最里面一层的数据才是我们要显示在页面上的数据
 * 这里的处理的方式是比较麻烦的一种,其中它处理的方式可以有好几种
 * 这里的数据层层嵌套,就像xml资源的子标签一样
 */

/*下面是提供API网站给我们的数据的提示,xml文件中下面的某些变量,我们可以选择性的去使用,
但是这些变量的名字是固定的,更改了就获取不到了
 allNum String  345 所有记录数
    allPages    String  45  所有页数。每页20条。
    contentlist JokeItem[]      笑话条目内容
    - title String  吃了一百年的玉米    笑话标题
    - text  String      笑话正文
    - ct    String  2015-07-10 05:54:00.000 生成时间
    currentPage String  1   当前第几页
    maxResult   String  20  每页最多显示几条*/

//因为要Intent来实现数据的传递,所以要实现序列化
public class JokeBean implements Serializable {
    //最外层的属性值
    int showapi_res_code;
    String showapi_res_error;
    Body showapi_res_body;//这个才是有用的信息数据,上面的实现其实也是可以不用去定义的

    @Override
    public String toString() {
        return "JokeBean{" +
                "showapi_res_body=" + showapi_res_body +
                ", showapi_res_code=" + showapi_res_code +
                ", showapi_res_error='" + showapi_res_error + '\\'' +
                '}';
    }

    class Body implements Serializable {
        int allNum;
        int allPages;
        int currentPage;//当前第几页
        int maxResult;
        int ret_code;
        ArrayList<Content> contentlist;

        @Override
        public String toString() {
            return "Body{" +
                    "allNum=" + allNum +
                    ", allPages=" + allPages +
                    ", currentPage=" + currentPage +
                    ", maxResult=" + maxResult +
                    ", ret_code=" + ret_code +
                    ", contentlist=" + contentlist +
                    '}';
        }

        class Content implements Serializable {
            String id;
            String ct;//生成时间
            String text;//笑话正文
            String title;//笑话标题
            int type;//文本笑话,图片笑话,动态图笑话
            String img;//笑话的图片连接地址URL

            //重写toString方法,查看数据
            @Override
            public String toString() {
                return "Content{" +
                        "ct='" + ct + '\\'' +
                        ", id='" + id + '\\'' +
                        ", text='" + text + '\\'' +
                        ", title='" + title + '\\'' +
                        ", type=" + type +
                        ", img='" + img + '\\'' +
                        '}';
            }
        }
    }

    /**
     * 创建一个静态的转换方法
     * 将字符串使用json解析的方式,转换成对象
     * 用于把资源代码的字符串中某些值赋值给某些需要的变量
     */
    public static JokeBean getBeanValue(String json) {
        try {
            //1.将最外层的字符串,转换为json对象
            JSONObject jsonObject = new JSONObject(json);
            //2.创建返回的对象
            JokeBean jokeBean = new JokeBean();
            //3.取外层的数据,两种方法opt和get,其中opt更好,get在数据不匹配时会报错
            jokeBean.showapi_res_code = jsonObject.optInt("showapi_res_code");
            jokeBean.showapi_res_error = jsonObject.optString("showapi_res_error");

            //4.取第二层数据,是一个对象
            JSONObject bodyObject = jsonObject.optJSONObject("showapi_res_body");
            //5.通过这个对象的值,再去取数据
            //创建内部对象,把获取到的数据赋值给这个类的对象
            Body body = jokeBean.new Body();
            body.allNum = bodyObject.optInt("allNum");
            body.allPages = bodyObject.optInt("allPages");
            body.currentPage = bodyObject.optInt("currentPage");
            body.maxResult = bodyObject.optInt("maxResult");
            body.ret_code = bodyObject.optInt("ret_code");
            //Log.e("TAG", "jokeBean------------>" + jokeBean.toString());
            // Log.e("TAG", "body------------>" + body.toString());
            //这里的contentlist的数据是数组类型的!
            JSONArray array = bodyObject.optJSONArray("contentlist");
            //创建一个集合用来存放数组
            body.contentlist = new ArrayList<>();
            //通过数据遍历循环去取所有的对象
            for (int i = 0; i < array.length(); i++) {
                Body.Content content = body.new Content();
                //再次使用json解析数据
                //集合通过optXXX(index)的方法去取值
                JSONObject obj = array.optJSONObject(i);
                content.ct = obj.optString("ct");//笑话的创建时间
                content.id = obj.optString("id");//笑话的id编号
                content.title = obj.optString("title");//笑话的标题
                content.type = obj.optInt("type");//笑话的类别,1代表文本,2代表图像

                //对类别的判断
                if (content.type == 2) {
                    content.img = obj.optString("img");
                } else {
                    content.text = obj.optString("text");
                }
                body.contentlist.add(content);
            }
            //Log.e("TAG", "body.c------------>" + body.contentlist.toString());
            jokeBean.showapi_res_body = body;
            //返回一个JokeBean对象,里面包含所有的数据
            return jokeBean;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
}

5.创建一个异步任务类,用来下载json数据

package com.lwz.conn.utils;

import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;

import com.lwz.conn.JokeBean;
import com.lwz.conn.ShowActivity;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 异步任务的创建
 * 这里的任务是下载网络的资源文件
 */

public class MyAsyncTask extends AsyncTask<String, Void, String> {
    Context context;

    public MyAsyncTask(Context context) {
        this.context = context;
    }

    //在子线程中做资源的下载
    @Override
    protected String doInBackground(String... params) {
        try {
            //从params中获取传过来的URL
            URL url = new URL(params[0]);
            Log.e("TAG", params[0]);
            //使用URLconnection的子类HttpURLconnection来请求连接更好
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);//设置要读取文件
            conn.setConnectTimeout(10000);//设置连接的最长时间
            InputStream is = conn.getInputStream();//获取连接的输入流
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建一个高速的输出流来读取输入流
            //对数据的读取(边读边取)
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = is.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }
            //获得的输出流变成String类型的字符串,用于最后的返回
            String result = new String(baos.toByteArray(), "utf-8");//设置编码格式
            //返回的是获取的一大串文本资源源码
            Log.e("TAG","-------------->"+ result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    //任务完成后页面的跳转,把相关数据带到要跳转的页面
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        //这里接收的s,就是从网络中获取到的一大串字符串的文件源码
        //这里要使用json解析,从源码中来获取我们需要的数据
        Log.e("TAG", s);
        JokeBean jokeBean = JokeBean.getBeanValue(s)Go 要如何才能解释的清!和 Json 之间的种种映射关系! 「含解决方案 & 代码实现,建议收藏!」

Android 网络编程解析JSON数据(11)

android中的网络解析xml,json,html框架

(建议收藏)计算机网络:传输层概述UDP协议与可靠传输协议习题解析与拓展

(建议收藏)计算机网络:应用层题目综合解析与拓展

Android解析服务器响应数据