Java发起HTTP请求并解析JSON返回数据

📚专栏

「Java数据集成」专栏

基础支撑
辅助(可选)
进阶
基础支撑
基础支撑
辅助(可选)
辅助(可选)
辅助(可选)
测试(可选)
《请求和解析》
《依批分增删改查》
《生成代码脚本》
《增删改查模板》
《同异步请求和处理》
《集成模板》
《HTTP请求工具类》
《JSON处理工具类》
《XML处理工具类》
《生成随机数据脚本》

💬相关

http 协议

https://www.cnblogs.com/mqy1/p/13884964.html


💬相关

本文进阶的博客文章《Java发起同异步HTTP请求和处理数据》,看完本文后感兴趣可以再查看

https://blog.csdn.net/weixin_42077074/article/details/129601132

发起 HTTP 请求并获得返回信息

requestHTTPContent() 函数中借助 HttpURLConnection 类实现发送请求

📑来源

代码改进自博客《JAVA如何调用对方http接口得到返回数据》

https://cloud.tencent.com/developer/article/2081582

public static String requestHTTPContent(String strURL, String method) throws Exception {
	
    URL url = new URL(strURL);
    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    
    // 设置请求方法,为 "GET" 或 "POST"
    // GET 请求只能传 query 参数,query 参数都是拼在请求地址上的
	// POST 可以传 body 和 query 两种形式的参数
    httpConn.setRequestMethod(method);

    // 请求时是否使用缓存
    httpConn.setUseCaches(false);
    
    // POST 请求必须设置下面两项
    // 设置是否从 HttpUrlConnection 的对象写
    httpConn.setDoOutput(true);
    // 设置是否从 HttpUrlConnection 的对象读入
    httpConn.setDoInput(true);

    httpConn.connect();

    BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
    String line;
    StringBuffer buffer = new StringBuffer();
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
    }
    
    reader.close();
    httpConn.disconnect();
    
    String res = buffer.toString();
    // 输出字符串形式的返回数据
    System.out.println(res);
    
    return res;
}

添加 HTTP 请求头

根据需求决定是否需要

  • 设置接受内容类型
  • 设置发送内容类型
  • 设置编码方式(字符集)
  • 添加自定义请求头

添加请求头在下面方法二选一

直接添加请求头

在前文 HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();httpConn.connect(); 之间添加以下代码

此处以发送和接受内容均为 JSON 格式,UTF-8 编码方式为例

	// 设置发送内容类型
    httpConn.setRequestProperty("Content-Type","application/json;charset=UTF-8");
    // 设置接收内容类型
    httpConn.setRequestProperty("Accept","application/json");
    // 设置编码方式(字符集)
    httpConn.setRequestProperty("charset", "UTF-8");
	// 添加自定义请求头,key 和 value 是你需要添加的头信息的键与值,如用于鉴权
	httpConn.setRequestProperty(key,value); 

注意,如果服务器的安全设置不接受 Java 程序作为客户端访问,则可以加上下面的代码

	// 设置访问者系统引擎版本、浏览器信息的字段信息,此处伪装成用户通过浏览器访问
	httpConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

借助 Map 添加请求头

如果复用率比较高的话,也可以考虑将请求头的键与值写进 Map 的对象里,Map 中键值对(key-value pair)被称作项(entry)

	Map<String, String> headers = new HashMap<String, String>(){{
		// 设置接收内容类型
		put("Accept","application/json");
		// 设置发送内容类型
		put("Content-Type","application/json;charset=UTF-8");
		// 设置字符集
		put("charset", "UTF-8");
 		// 设置访问者系统引擎版本、浏览器信息的字段信息,此处伪装成用户通过浏览器访问
		put("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");       
        // 添加自定义请求头,key 和 value 是你需要添加的头信息的键与值,如用于鉴权
		put(key,value); 
	}};

通过函数 addHeadersToRequest() 遍历 Map 的对象添加请求头

// 将请求头键值对添加到 HTTP 请求中
public static void addHeadersToRequest(HttpURLConnection httpConn, Map<String, ?> headers) {
    if (headers != null) {
        for (Map.Entry<String, ?> entry : headers.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value.getClass().isArray()) {
                // 如果是数组类型,则遍历数组并添加请求头
                for (Object v : (Object[]) value) {
                    httpConn.setRequestProperty(key, v.toString());
                }
            } else {
                // 如果不是数组类型,则直接添加请求头
                httpConn.setRequestProperty(key, value.toString());
            }
        }
    }
}

忽略验证 HTTPS 中 SSL 证书

一般用于 SSL 证书失效,却又不得不以 HTTPS 去请求的情况,如报错 java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xxx.xxx.xxx found

在发起 HTTPS 请求前调用下文 disableSSLVerification() 函数

📑来源

代码源自博客

https://www.cnblogs.com/Springmoon-venn/p/7504901.html

// 禁用 SSL 验证
public static void disableSSLVerification() {
    try {
        // 创建不验证证书链的 TrustManager
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
                                                         };

        // 安装 TrustManager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // 创建验证所有主机名的 HostnameVerifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // 安装 HostnameVerifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}

添加 query 请求参数

query 请求参数是拼接在请求 URL 上的,下面方法二选一

字符串拼接进 URL

如果想简单粗暴,则直接手敲含有请求参数的字符串,通过函数 concatParamsToURL() 直接拼接在 URL 字符串末尾

public String concatParamsToURL(String staticURL, String paramsStr) throws Exception {
    return staticURL + paramsStr;
}

Map 键值对拼接进 URL

如果想将变量作为请求参数,则可以考虑将参数名和参数值放进 Map 的对象

// 无重复同名参数
Map<String, String> params1 = new HashMap<String, String>(){{
    put("param1","value1");
    put("param2","value2");
    put("param3","value3");
}};
// 含重复同名参数,但一般不推荐
Map<String, String[]> params2 = new HashMap<String, String[]>(){{
    put("param1",new String[]{"value11","value12"});
    put("param2",new String[]{"value21","value22"});
    put("param3",new String[]{"value31","value32"});
}};

通过函数 concatParamsToURL() 把参数拼接在 URL 字符串末尾

public static String concatParamsToURL(String staticURL, Map<String, ?> params) throws Exception {
    // staticURL 是字符串形式的静态 URL
    // params 键与值分别是参数名与参数值,URL 有重复同名参数时将多个值放进数组

    // 判断参数是否为空
    if (params.isEmpty()) {
        return staticURL;
    }

    StringBuilder sb = new StringBuilder(staticURL);

    // 判断 URL 中是否已经包含参数
    boolean hasParams = staticURL.indexOf("?") != -1;

    // 遍历参数
    for (Map.Entry<String, ?> entry : params.entrySet()) {
        String key = entry.getKey(); // 参数名
        Object value = entry.getValue(); // 参数值

        // 判断参数值是否为数组
        if (value.getClass().isArray()) {
            // 如果是数组,遍历数组并添加参数
            for (Object v : (Object[]) value) {
                sb.append(hasParams ? "&" : "?")
                    .append(URLEncoder.encode(key, "utf-8"))
                    .append("=")
                    .append(URLEncoder.encode(v.toString(), "utf-8"));
                hasParams = true;
            }
        } else {
            // 如果不是数组,直接添加参数
            sb.append(hasParams ? "&" : "?")
                .append(URLEncoder.encode(key, "utf-8"))
                .append("=")
                .append(URLEncoder.encode(value.toString(), "utf-8"));
            hasParams = true;
        }
    }

    return sb.toString();
}

添加 body 请求参数

此处以添加 JSON 形式的 body 请求参数为例,由于 JSON 不推荐出现重复键,因而此处暂时没有考虑重复同名参数的情况

💬相关

网页——Java 中 JSON 的使用,菜鸟教程

https://www.runoob.com/w3cnote/java-json-instro.html

需先在 Maven 的 pom.xml 加上依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

后在 Java 中引入包

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

body 请求参数只能使用 POST 方法进行请求,需要将前文的 httpConn.connect(); 替换成下面的代码,二选一

手动生成 JSON 对象

如果想手动生成 JSON 对象,那么选这个

    JSONObject paramsJSON = new JSONObject();
    // 发送的 JSON 的属性与值 
    paramsJSON.put("attr1", "value1");
    paramsJSON.put("attr2", "value2");
    // 发送请求
    OutputStream out = new DataOutputStream(httpConn.getOutputStream());
    // getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
    out.write(paramsJSON.toJSONString().getBytes("UTF-8"));
    out.flush();

Map 对象转化成 JSON 对象

如果想将含有请求参数的 Map 的对象转化成 JSON 对象,那么选这个

    // 发送的 JSON 对象的键与值 
    Map<String, String> paramsMap = new HashMap<String, String>(){{
        put("attr1", "value1");
        put("attr2", "value2");
    }};
    OutputStream out = new DataOutputStream(httpConn.getOutputStream());
    // getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
    out.write(JSON.toJSONString(paramsMap).getBytes("UTF-8"));
    out.flush();

解析 JSON 字符串形式的返回数据

添加前文 JSON 所需的相关依赖,并在前文 String res = buffer.toString();return res; 之间调用函数 printJSON(),函数内解析 JSON 的三种方法自行视情况而选择

📑来源

代码改进自博客

https://blog.csdn.net/qq_43370892/article/details/114805511

public void printJSON(String jsonStr) {
    // 给定字符串类型的JSON数据,如 {"code":"0","error":null,"message":"success","data":[{"x":"1","y":"2"},{"x":"3","y":"4"}]}
    
	//先转换成 JSONObject 类型
    JSONObject jsonObj = JSON.parseObject(jsonStr);
    
    //1.全部输出,直接遍历 JSONObject 中的键与值
    if(jsonObj != null) for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
    
    //2.指定属性输出,通过 JSONObject 中的getString("key")方法,得到对应的值
    if(jsonObj != null) System.out.println("message:"+jsonObj.getString("message"));

    //3.指定属性输出,但属性含有数组的,下文以 data 为例
    if(jsonObj != null){
        JSONArray jsonInfo = JSONObject.parseArray(jsonObj.getString("data"));//将jsonObj解析成json数组
        if(jsonInfo != null) for (int i = 0; i < jsonInfo.size(); i++) {//遍历数组
            JSONObject jsonDetailInfo = jsonInfo.getJSONObject(i);//根据下标以此拿数据,每一个数组元素又是一个 JSONObject 对象,所以用JSONObject接收
            String x = jsonDetailInfo.getString("x");
            String y = jsonDetailInfo.getString("y");
            //输出当前获取的数据
            System.out.println("x="+x+";y="+y);
        }        
    }
}

💬相关

更为详细的 JSON 处理方法可以查看博客文章《JavaJSON处理工具类JSONUtils》

https://blog.csdn.net/weixin_42077074/article/details/129364274

综合改进后的发起 HTTP 请求并获得返回信息

综合改进后的请求函数 requestHTTPContent(),其中有调用前后文的

  • 添加请求头函数:addHeadersToRequest()
  • 参数拼接函数:concatParamsToURL()
  • 忽略 SSL 验证函数:disableSSLVerification()
  • 读取函数:readResponseContent()
  • 输出函数:outputResponseContent()
// 发起 HTTP 请求并获取响应内容
// 重载 requestHTTPContent(),相当于参数有默认值
public static String requestHTTPContent(String strURL) throws Exception {
    return requestHTTPContent(strURL, "GET", null, null);
}
public static String requestHTTPContent(String strURL, String method) throws Exception {
    return requestHTTPContent(strURL, method, null, null);
}
public static String requestHTTPContent(String strURL, String method, Map<String, ?> headers) throws Exception {
    return requestHTTPContent(strURL, method, headers, null);
}
public static String requestHTTPContent(String strURL, String method, Map<String, ?> headers, Map<String, ?> params) throws Exception {
    // strURL 是 String 类型的 URL
    // method 是 String 类型的请求方法,为 "GET" 或 "POST"
    // headers 键与值分别是请求头名与请求头值,有重复同名请求头时将多个值放进数组
    // params 键与值分别是参数名与参数值,URL 有重复同名参数时将多个值放进数组

    // 忽略验证 https 中 SSL 证书
    disableSSLVerification();

    // GET 方法下,query 参数拼接在 URL 字符串末尾
    if(method.equals("GET") && params != null) {
        strURL = concatParamsToURL(strURL, params);
    }

    System.out.println(strURL);

    URL url = new URL(strURL);
    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setRequestMethod(method);

    // 添加 HTTP 请求头
    addHeadersToRequest(httpConn, headers);

    // 请求时是否使用缓存
    httpConn.setUseCaches(false);

    // POST 方法请求必须设置下面两项
    // 设置是否从 HttpUrlConnection 的对象写
    httpConn.setDoOutput(true);
    // 设置是否从 HttpUrlConnection 的对象读入
    httpConn.setDoInput(true);

    // 此处默认 POST 方法发送的内容就是 JSON 形式的 body 参数,可以自行更改
    if(method.equals("POST") && params!=null) {
        // 发送请求
        OutputStream out = new DataOutputStream(httpConn.getOutputStream());
        // getBytes() 作用为根据参数给定的编码方式,将一个字符串转化为一个字节数组
        out.write(JSON.toJSONString(params).getBytes("UTF-8"));
        out.flush();
    }
    else{
        //发送请求
        httpConn.connect();
    }

    String contentType = httpConn.getContentType();
    String result = readResponseContent(httpConn);

    // 输出响应内容
    outputResponseContent(result, contentType);

    return result;
}

// 读取响应内容
private static String readResponseContent(HttpURLConnection httpConn) throws Exception {
    BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
    String line;
    StringBuffer buffer = new StringBuffer();
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
    }
    reader.close();
    return buffer.toString();
}

// 输出响应内容
public void outputResponseContent(String responseContent, String contentType){
    // contentType 是接收内容类型,如"application/json"、"application/xml"、"text/html"、"text/plain"等,此处自定义输出方法
    if(contentType.contains("application/json")){
        JSONObject jsonObj = JSON.parseObject(responseContent);
        if(jsonObj != null) for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }
    else{
        System.out.println(responseContent);
    }
}

💬相关

更为全面的输出响应内容函数可以查看博客文章《JavaHTTP请求工具类HTTPUtils》

https://blog.csdn.net/weixin_42077074/article/details/129625934

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,请求网络并解析 JSON 数据可以使用常见的网络请求库和 JSON 解析库。以下是使用 OkHttp 和 Gson 进行网络请求和 JSON 解析的示例代码。 1. 添加依赖 在 build.gradle 文件中添加以下依赖: ``` dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.0' implementation 'com.google.code.gson:gson:2.8.6' } ``` 2. 发起网络请求 使用 OkHttp 发起 GET 请求,并将返回JSON 数据作为字符串返回。 ``` public static String doGetRequest(String url) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return response.body().string(); } ``` 3. 解析 JSON 数据 使用 Gson 解析 JSON 数据,并将其转换为 Java 对象。 例如,假设我们有一个包含人名和年龄的 JSON 数据: ``` { "people": [ { "name": "Tom", "age": 25 }, { "name": "Bob", "age": 30 }, { "name": "Alice", "age": 27 } ] } ``` 我们可以定义一个 Person 类来表示每个人,并使用 Gson 将 JSON 数据转换为 Person 类的 List。 ``` public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public static List<Person> parseJson(String json) { Gson gson = new Gson(); Type type = new TypeToken<List<Person>>(){}.getType(); return gson.fromJson(json, type); } ``` 4. 使用示例 在 Activity 或 Fragment 中使用以上代码进行网络请求和 JSON 解析。 ``` new Thread(() -> { try { String json = doGetRequest(url); List<Person> people = parseJson(json); // 在 UI 线程中更新 UI runOnUiThread(() -> { // 处理返回数据 }); } catch (IOException e) { e.printStackTrace(); } }).start(); ``` 其中,url 是请求的地址,可以是任何支持 GET 请求的 API。在 Android 开发中,为了避免在主线程中执行耗时操作,建议将网络请求放在子线程中执行。在使用返回数据更新 UI 时,需要使用 runOnUiThread 方法切换到主线程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值