当前位置:

首页 > 编程开发 > Java实现HTTP请求与JSON解析的完整代码示例

Java实现HTTP请求与JSON解析的完整代码示例

本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

要在Java中获取网络接口数据并提取内容,核心工作就是两件事:通过网络客户端向指定URL发出HTTP请求拿到响应字符串,随后使用解析器把这串JSON文本转换为程序可直接调用的Java对象。在现代Java工程中,最标准、最干净的做法是直接使用Java内置的java.net.http.HttpClient完成网络交互,并搭配工业级工具包Jackson完成JSON序列化与反序列化。本文将提供一套可直接运行的完整工程代码,并拆解关键执行细节与边界注意事项。

Java实现HTTP请求与JSON解析的完整代码示例
图 1:网络传输与实体解析的核心数据流向

1. 依赖准备与基础环境

很多刚开始写网络请求的开发者经常遇到一个困惑:旧教程里常常使用已经过时的HttpURLConnection或依赖庞大的第三方Apache HttpClient。实际上,自Java 11起,JDK就标准化并内置了现代化的java.net.http.HttpClient,它原生支持异步、同步及HTTP/2协议,无需额外引入网络通信依赖。

在JSON处理方面,虽然也可以手动解析字符串,但工业界标准方案是使用类型安全的对象映射器。这里我们选择最稳健、生态支持最广泛的Jackson。如果你的项目使用Maven,只需在pom.xml中加入jackson-databind即可:



    com.fasterxml.jackson.core
    jackson-databind
    2.17.0

2. 定义数据模型实体类(POJO)

在发起请求前,需要先定义一个接收数据的载体。假设我们调用的接口返回一个包含用户基本信息的JSON:

{
  "id": 1001,
  "name": "张伟",
  "email": "zhangwei@example.com"
}

针对这段结构,我们建立对应的Java实体类。Jackson要求实体类必须具备无参构造方法以及标准的getter/setter,或者通过合理的注解辅助。这里建议添加@JsonIgnoreProperties(ignoreUnknown = true),这样如果接口未来返回了多余字段,解析时不会抛出异常中断运行。

package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class UserProfile {
    private Long id;
    private String name;
    private String email;

    // 必须保留无参构造器供Jackson反射实例化
    public UserProfile() {
    }

    public UserProfile(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    @Override
    public String toString() {
        return "UserProfile{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

3. 执行流程与实现步骤

使用内置HttpClient和Jackson完成一次交互,需要遵循清晰的时序步骤。为了避免在请求挂起时造成线程永久阻塞,配置超时时间是构建可靠客户端的第一要务。

Java实现HTTP请求与JSON解析的完整代码示例
图 2:HTTP请求发起与数据解析操作步骤

4. 完整代码示例:GET与POST操作

以下为一个可以直接编译运行的完整类文件。程序内部包含了两个常见场景:通过GET方法获取远端JSON并反序列化为实体类,以及将本地实体类转换为JSON并通过POST提交给目标接口。

package com.example.demo;

import com.example.demo.model.UserProfile;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class HttpJsonDemo {

    // 推荐保持全局单例复用,复用内部连接池
    private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(5))
            .build();

    // ObjectMapper同样是线程安全的,推荐单例复用
    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static void main(String[] args) {
        String testUrl = "https://jsonplaceholder.typicode.com/users/1";

        try {
            System.out.println("=== 1. 执行 GET 请求并解析 JSON ===");
            UserProfile user = executeGet(testUrl);
            System.out.println("成功解析为实体: " + user);

            System.out.println("\n=== 2. 执行 POST 请求并提交 JSON ===");
            UserProfile newUser = new UserProfile(101L, "李雷", "lilei@example.com");
            String postUrl = "https://jsonplaceholder.typicode.com/users";
            String responseBody = executePost(postUrl, newUser);
            System.out.println("服务端返回结果:\n" + responseBody);

        } catch (IOException | InterruptedException e) {
            System.err.println("请求处理失败: " + e.getMessage());
            Thread.currentThread().interrupt(); // 保持中断标志位
        }
    }

    /**
     * 发送 GET 请求并解析单体对象
     */
    public static UserProfile executeGet(String url) throws IOException, InterruptedException {
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(10))
                .header("Accept", "application/json")
                .GET()
                .build();

        HttpResponse response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new RuntimeException("HTTP 响应失败,状态码: " + response.statusCode());
        }

        // 解析 JSON 字符串到目标实体
        return MAPPER.readValue(response.body(), UserProfile.class);
    }

    /**
     * 将实体序列化为 JSON,并执行 POST 提交
     */
    public static String executePost(String url, UserProfile payload) throws IOException, InterruptedException {
        // 将对象序列化为 JSON 字符串
        String jsonString = MAPPER.writeValueAsString(payload);

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(10))
                .header("Content-Type", "application/json; charset=UTF-8")
                .header("Accept", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonString))
                .build();

        HttpResponse response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new RuntimeException("HTTP POST 失败,状态码: " + response.statusCode());
        }

        return response.body();
    }
}

5. 复杂结构:解析集合与泛型对象

在实际业务中,接口很少总是返回一个纯粹的单体对象,往往返回的是一个包含多个对象的数组列表,或者带有状态码、消息和业务数据包裹的泛型对象:

// 场景 A: 列表返回
[ {"id":1,"name":"Alice"}, {"id":2,"name":"Bob"} ]

// 场景 B: 包装体返回
{ "code": 0, "msg": "ok", "data": { "id": 1, "name": "Alice" } }

在Java中,由于泛型在编译后会发生类型擦除,如果直接调用MAPPER.readValue(json, List.class)会导致编译不通过。正确的做法是借助Jackson提供的TypeReference保留运行时类型信息。

Java实现HTTP请求与JSON解析的完整代码示例
图 3:泛型擦除与 TypeReference 的解析机制
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.List;

// 针对集合结构的解析代码
String jsonArrayString = "[{\"id\":1,\"name\":\"张伟\"},{\"id\":2,\"name\":\"李娜\"}]";

List userList = MAPPER.readValue(
        jsonArrayString, 
        new TypeReference>() {}
);

for (UserProfile u : userList) {
    System.out.println("用户ID: " + u.getId() + ", 名字: " + u.getName());
}

6. 关键注意事项与工程化经验

避坑提示:客户端与映射器的生命周期

不要在每个业务方法中都通过 HttpClient.newHttpClient() 或 new ObjectMapper() 去创建实例。这两个对象的初始化成本较高,尤其是 HttpClient 内部维系着线程池和长连接(Keep-Alive)。把它们声明为静态常量或通过依赖注入注入为单例,可以大幅避免在高并发场景下文件描述符被耗尽的问题。

除了生命周期之外,在实际网络交互中还有几个常见问题需要防范:

  • 连接与读取超时必须设置: 永远不要发起未配置超时的请求。默认情况下,如果不显式指定超时,一旦远端服务器出现网络黑洞或网关假死,调用线程将会永久挂起。
  • 状态码非200的处理: 服务端返回404或500错误时,HTTP请求本身通常是成功通信的(不会抛出IOException),但返回的Body往往是报错页面的HTML或特定的错误JSON。必须先判断response.statusCode(),不要把错误信息直接塞给readValue(),否则会抛出无意义的JSON解析异常。
  • 命名格式差异处理: 如果接口服务端字段采用下划线命名(如 user_name),而Java实体类采用驼峰命名(如 userName),可以在属性上配置 @JsonProperty("user_name"),或直接对全局Mapper配置 PropertyNamingStrategies.SNAKE_CASE。

7. 核心要点梳理与技术选型对照

在实现网络请求和数据反序列化时,不同技术路线的特性对比与全流程要点总结如下:

Java实现HTTP请求与JSON解析的完整代码示例
图 4:技术选型对照与关键开发考量汇总

通过这套组合,开发者无需引入笨重的外部HTTP包,只需少量标准化代码,就能在Java项目中完成高可靠的HTTP请求发起与数据解析工作。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 Java httpclient jackson Http请求 Java代码 JSON解析
相关文章 更多
Java递归出现StackOverflowError的原因分析及栈空间优化方案
Java递归出现StackOverflowError的原因分析及栈空间优化方案

详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

Java空指针异常(NPE)的代码排查与修复实例
Java空指针异常(NPE)的代码排查与修复实例

针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

selenium上传文件教程本地文件路径设置方法
selenium上传文件教程本地文件路径设置方法

深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

Java抽象方法修饰符限制:为何不能用private或static
Java抽象方法修饰符限制:为何不能用private或static

深入剖析Java中抽象方法为何严禁使用private和static修饰符。从面向对象契约规范、方法继承重写、JVM动态绑定(invokevirtual)与静态解析(invokestatic)等底层机制展开详细推导,结合编译报错示例与全景对比,彻底理清修饰符限制背后的设计逻辑。

Java变量声明与初始化:局部、成员及静态变量的定义语法
Java变量声明与初始化:局部、成员及静态变量的定义语法

系统解析Java局部变量、成员变量与静态变量的定义语法、声明与初始化机制、生命周期及JVM内存驻留规则,结合图解与代码示例分析常见编译错误与认知误区。

Java 8至21新特性代码写法对比:Lambda、Record与Switch
Java 8至21新特性代码写法对比:Lambda、Record与Switch

本文通过具体的旧版与新版代码对比,详细剖析Java 8引入的Lambda表达式、Java 14/16引入的Record类,以及Java 12至21逐步演进完善的Switch表达式与模式匹配,展示代码简化路径与避坑要点。

Java子类未实现抽象方法编译错误修复指南
Java子类未实现抽象方法编译错误修复指南

针对Java开发中常见的“子类未实现抽象方法”编译错误,深入分析报错原因,提供重写实现、声明抽象子类两种标准修复路径,并总结参数签名、访问修饰符等典型避坑要点。

junit怎么用零基础完成第一个单元测试教程
junit怎么用零基础完成第一个单元测试教程

适合初学者的JUnit入门指南,详解如何配置环境、编写首个测试用例、使用断言验证结果,并分析单元测试的适用场景与例外情况。

PHP发送HTTP请求的方法及完整代码教程
PHP发送HTTP请求的方法及完整代码教程

详解PHP中发送HTTP请求的常用方法,包括原生cURL配置、file_get_contents流操作及Guzzle库的使用,提供GET/POST请求的完整代码示例与注意事项。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
AirBuddy 3 macOS版
AirBuddy 3 macOS版
macOS

AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

AirServer macOS版
AirServer macOS版
macOS

AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

AnyDesk macOS版
AnyDesk macOS版
macOS

AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

WINDOWS 更多
讯飞绘文 网页版
讯飞绘文 网页版
Windows

讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

AirServer Windows版
AirServer Windows版
Windows

AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

AlwaysUp Windows版
AlwaysUp Windows版
Windows

AlwaysUp是一款面向Windows的系统服务注册与程序托管工具,可让普通应用、脚本及批处理在无人登录时随系统启动,并通过状态检测、异常重启、资源监控和邮件通知保障关键任务持续运行。