什么是 JSON?学习JSON有什么用?在springboot项目里如何实现JSON的序列化和反序列化?

作为一个学习Javaweb的新手,理解JSON的序列化和反序列化非常重要,因为它在现代Web开发,特别是Spring Boot中无处不在。

什么是 JSON?

首先,我们简单了解一下JSON (JavaScript Object Notation)。
JSON 是一种轻量级的数据交换格式。它基于JavaScript编程语言的一个子集,但是独立于语言,也就是说,几乎所有的编程语言都有解析和生成JSON数据的库。

JSON 的主要特点:

  • 易于人阅读和编写。

  • 易于机器解析和生成。

  • 常用于前后端之间的数据交换(比如浏览器和服务器之间)、API之间的数据传输。

  • 基本结构是:

    • 对象 (Object): 由键值对(key: value)组成,键是字符串,值可以是字符串、数字、布尔值、数组、对象或 null。对象用花括号 {} 包围。

      {"name": "张三","age": 30,"isStudent": false
      }
      
    • 数组 (Array): 由有序的值(可以是任何JSON类型)组成。数组用方括号 [] 包围。

      ["苹果","香蕉","橙子"
      ]
      
    • 值 (Value): 字符串、数字、布尔值 (true/false)、null、对象或数组。

什么是 序列化 (Serialization)?

概念: 将一个Java对象转换成JSON格式的字符串的过程,就叫做 JSON序列化

为什么需要?
当你的Spring Boot应用需要将数据显示给前端(比如Web页面、移动App)或者发送给其他服务时,你需要将你的Java对象(比如一个表示用户的 User 对象,一个表示商品的 Product 对象)转换成一种标准格式,以便接收方能够理解。JSON就是最常用的标准格式之一。

想象一下:你的Java程序里有一个 Product 对象,它包含了 idnameprice 等属性。你不能直接把这个Java对象“发送”出去。你需要把它包装成一个字符串,这个字符串的格式就是JSON。

Java对象 (Product)  ───────>  JSON字符串
{ id: 1, name: "Laptop", price: 8000.0 }  ─序列化─>  '{"id":1,"name":"Laptop","price":8000.0}'

什么是 反序列化 (Deserialization)?

概念: 将一个JSON格式的字符串转换成对应的Java对象的过程,就叫做 JSON反序列化

为什么需要?
当你的Spring Boot应用从前端(比如用户提交的表单数据、通过API接收到的请求体)或其他服务接收到数据时,这些数据通常是JSON格式的字符串。为了在你的Java程序中处理这些数据,你需要将这些JSON字符串转换成你可以操作的Java对象。

想象一下:前端通过一个表单提交了一个新商品的信息,数据以JSON字符串的形式发送到你的Spring Boot后端。你需要把这个JSON字符串转换回一个 Product Java对象,这样你才能方便地访问 nameprice 等属性,并进行业务逻辑处理(比如保存到数据库)。

JSON字符串  ───────>  Java对象
'{"name":"Keyboard","price":300.0}'  ─反序列化─>  Java对象 (Product: { name: "Keyboard", price: 300.0 })

Spring Boot 如何实现 JSON 序列化和反序列化?

这是Spring Boot的强大之处:它自动化地处理了大部分情况下的JSON序列化和反序列化!

核心依赖:

在你的pom.xml文件中,如果你使用了spring-boot-starter-web这个依赖,那么你就已经自动引入了处理JSON所需的所有库。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter-web 依赖会间接地引入 spring-boot-starter-json 依赖,而 spring-boot-starter-json 默认使用的是 Jackson 这个库来处理JSON。

Jackson 库:

Jackson 是一个非常流行和强大的Java库,专门用于处理JSON。Spring Boot通过自动配置,将Jackson设置为默认的 HttpMessageConverter

HttpMessageConverter 是 Spring MVC 中的一个核心概念,它负责将HTTP请求体转换成Java对象(反序列化),以及将Java对象转换成HTTP响应体(序列化)。当Spring Boot检测到请求或响应涉及JSON时,它就会使用配置好的Jackson HttpMessageConverter 来完成转换。

自动化体现在哪里?

在你编写Spring Boot的Controller时,只需要使用特定的注解:

  1. 反序列化 (@RequestBody): 当你的Controller方法的参数前面加上 @RequestBody 注解时,Spring Boot会自动尝试将HTTP请求体中的JSON字符串反序列化成这个参数对应的Java对象。
  2. 序列化 (@ResponseBody@RestController):
    • 如果你的Controller类使用了 @RestController 注解(它是 @Controller@ResponseBody 的组合),或者你的方法使用了 @ResponseBody 注解,Spring Boot会自动尝试将方法的返回值序列化成JSON字符串,并作为HTTP响应体发送出去。

简单来说,Spring Boot + Jackson 让你在大多数情况下,只需要关注你的Java对象和Controller方法,而不需要手动编写JSON解析和生成的代码。

学习 JSON 序列化和反序列化有什么用?

对于新手来说,学习这个概念以及Spring Boot如何处理它,至少有以下几个重要的用途:

  1. 理解 Web API 工作原理: 现代Web应用绝大多数都使用JSON进行前后端数据交互。理解序列化/反序列化是理解Spring Boot如何构建和响应API请求的基础。你知道为什么你返回一个Java对象,前端却收到了JSON数据;你知道为什么前端发送JSON数据,你却可以直接在方法参数中拿到一个Java对象。
  2. 开发 RESTful API: Spring Boot是构建RESTful API的强大框架。RESTful API的核心就是通过HTTP请求(GET, POST, PUT, DELETE等)和JSON数据进行资源的交互。掌握JSON处理是开发API的必备技能。
  3. 数据交换和集成: 除了前后端,不同的微服务之间、你的服务和其他第三方服务之间也经常使用JSON交换数据。理解如何处理JSON是进行系统集成和数据交换的基础。
  4. 调试和排错: 当API调用失败时,你可能会看到JSON解析或生成相关的错误(比如 HttpMessageNotReadableException 反序列化失败,或者序列化结果不符合预期)。理解底层机制可以帮助你更快地定位和解决问题。
  5. 定制化需求: 虽然Spring Boot自动化处理了很多,但有时你需要更精细地控制JSON的输出格式(比如日期格式、忽略某些字段、改变字段名等)。这时你需要了解Jackson提供的注解,而这些注解是基于序列化/反序列化的概念工作的。
  6. 数据存储和配置文件: 有些应用会将数据以JSON格式存储(比如NoSQL数据库的一些场景),或者使用JSON作为配置文件格式。了解JSON处理有助于你读写这些数据。

实践示例 (Spring Boot 项目)

我们通过一个简单的例子来演示。

1. Maven 依赖 (确保 spring-boot-starter-webpom.xml 中):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.5</version> <!-- 使用你项目的实际版本 --><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>json-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>json-demo</name><description>Demo project for JSON serialization/deserialization</description><properties><java.version>17</java.version> <!-- 使用你的Java版本 --></properties><dependencies><!-- 这个依赖会自动引入 spring-boot-starter-json (包含 Jackson) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot 测试依赖 (可选) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

2. 创建一个简单的 Java 对象 (POJO):

这个对象将用于表示我们要在Java代码中操作的数据结构。Jackson在进行反序列化时,默认会寻找无参构造函数,以及通过getter/setter方法来匹配JSON字段和对象属性。为了简化,我们使用Lombok库来自动生成构造函数、getter/setter等。如果你不用Lombok,需要手动添加。

// Product.java
package com.example.jsondemo.model;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;@Data // 自动生成 getter, setter, toString, equals, hashCode
@NoArgsConstructor // 自动生成无参构造函数 (反序列化需要)
@AllArgsConstructor // 自动生成全参构造函数 (可选,方便创建对象)
public class Product {private Long id;private String name;private double price;// 如果不用 Lombok,你需要手动添加:// public Product() {} // 无参构造函数// public Product(Long id, String name, double price) { ... } // 全参构造函数// public Long getId() { ... }// public void setId(Long id) { ... }// public String getName() { ... }// public void setName(String name) { ... }// public double getPrice() { ... }// public void setPrice(double price) { ... }
}

注意:如果你没有使用Lombok,需要手动添加Lombok的Maven依赖并在IDE中安装Lombok插件。或者手动写出构造函数和getter/setter方法。

3. 创建一个 Spring Boot Controller:

这个Controller将演示如何接收JSON数据(反序列化)和返回JSON数据(序列化)。

// ProductController.java
package com.example.jsondemo.controller;import com.example.jsondemo.model.Product;
import org.springframework.web.bind.annotation.*;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;@RestController // @RestController 包含了 @Controller 和 @ResponseBody
@RequestMapping("/api/products")
public class ProductController {// 模拟一个存储商品的列表 (实际应用中通常是数据库)private List<Product> productList = new ArrayList<>();// 用于生成唯一的IDprivate AtomicLong nextId = new AtomicLong(1);// === 演示 JSON 反序列化 ===// 这个方法接收一个 POST 请求,请求体是 JSON 格式的 Product 对象@PostMappingpublic String createProduct(@RequestBody Product product) {// @RequestBody: Spring Boot (通过 Jackson) 会自动把请求体中的 JSON 字符串// 反序列化成一个 Product Java 对象,并赋值给 product 参数。System.out.println("接收到产品信息:");System.out.println("Name: " + product.getName());System.out.println("Price: " + product.getPrice());// 模拟保存商品并赋予IDproduct.setId(nextId.getAndIncrement());productList.add(product);// 返回一个简单的字符串作为响应return "产品已创建,ID为: " + product.getId();}// === 演示 JSON 序列化 ===// 这个方法接收一个 GET 请求,并返回一个 Product 对象@GetMapping("/{id}")public Product getProductById(@PathVariable Long id) {// Spring Boot (通过 Jackson) 会自动把返回的 Product Java 对象// 序列化成 JSON 字符串,作为响应体发送出去。// 模拟从列表中查找商品 (实际应用中是查询数据库)for (Product product : productList) {if (product.getId().equals(id)) {System.out.println("正在返回产品信息 (将序列化为JSON): " + product);return product; // 返回 Java 对象}}// 如果找不到,返回 null (默认情况下 Jackson 会序列化为 'null')// 更健壮的做法是抛出异常或返回 ResponseEntity<Product> with status 404System.out.println("未找到ID为 " + id + " 的产品");return null;}// 演示返回一个列表的序列化@GetMappingpublic List<Product> getAllProducts() {// Spring Boot (通过 Jackson) 会自动把返回的 List<Product> 对象// 序列化成 JSON 数组,作为响应体发送出去。System.out.println("正在返回所有产品列表 (将序列化为JSON数组)");return productList;}
}

如何测试:

  1. 启动你的Spring Boot应用。

  2. 使用工具(如 Postman, cURL, Insomnia)进行测试:

    • 测试反序列化 (POST请求):

      • URL: http://localhost:8080/api/products (如果你的应用运行在默认端口8080)

      • Method: POST

      • Headers: Content-Type: application/json

      • Body: 选择 raw 并选择 JSON,输入以下JSON:

        {"name": "Wireless Mouse","price": 25.50
        }
        
      • 发送请求。你应该在控制台看到打印的接收信息,并收到一个包含新产品ID的响应。

    • 测试序列化 (GET请求):

      • 假设上一步创建的产品ID是1。

      • URL: http://localhost:8080/api/products/1

      • Method: GET

      • 发送请求。你应该收到一个包含该产品信息的JSON响应,类似这样:

        {"id": 1,"name": "Wireless Mouse","price": 25.5
        }
        
      • 测试返回列表 (GET请求):

        • URL: http://localhost:8080/api/products
        • Method: GET
        • 发送请求。你应该收到一个JSON数组,包含所有已创建的产品。

更进一步:Jackson 注解 (Customization)

虽然自动化很方便,但有时你需要控制JSON的输出。Jackson提供了很多注解,可以在你的POJO类属性或Getter/Setter方法上使用:

  • @JsonIgnore: 忽略某个属性,不进行序列化和反序列化。
  • @JsonProperty("newFieldName"): 改变属性在JSON中的字段名。
  • @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss"): 控制日期/时间字段的格式。
  • @JsonInclude(JsonInclude.Include.NON_NULL): 在序列化时,如果属性值为null,则不包含该字段。
  • @JsonCreator, @JsonDeserialize, @JsonSerialize: 更高级的定制。

这些注解让你能够精细地调整Java对象和JSON之间的映射关系。

总结

  1. JSON 是一种常用的数据交换格式。
  2. 序列化 是将 Java 对象转换为 JSON 字符串。
  3. 反序列化 是将 JSON 字符串转换为 Java 对象。
  4. 在 Spring Boot 项目中,通过引入 spring-boot-starter-web (它包含了 Jackson 库),Spring Boot 会自动配置 Jackson 作为默认的 HttpMessageConverter
  5. 你只需要在 Controller 方法中使用 @RequestBody (用于反序列化请求体) 和 @ResponseBody (或使用 @RestController,用于序列化返回值),Spring Boot 就会自动完成 JSON 的转换工作。
  6. 学习这些有助于你理解和开发 Web API,进行数据交互,以及更好地调试应用。

希望这个详细的解释能帮助你这个新手更好地理解 Spring Boot 中的 JSON 处理!多动手实践,你会越来越熟悉的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/78406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS/Android 使用 C++ 跨平台模块时的内存与生命周期管理

在移动应用开发领域,跨平台开发已经成为一种不可忽视的趋势。随着智能手机市场的持续扩张,开发者需要同时满足iOS和Android两大主流平台的需求,而这往往意味着重复的工作量和高昂的维护成本。跨平台开发的目标在于通过一套代码库实现多平台的支持,从而降低开发成本、加速产…

【AAudio】A2dp sink创建音频轨道的源码流程分析

一、AAudio概述 AAudio 是 Android 8.0(API 级别 26)引入的 C/C++ 原生音频 API,专为需要低延迟、高性能音频处理的应用设计,尤其适用于实时音频应用(如音频合成器、音乐制作工具、游戏音效等)。 1.1 主要特点 低延迟:通过减少音频数据在内核与用户空间之间的拷贝,直…

Spring中配置 Bean 的两种方式:XML 配置 和 Java 配置类

在 Spring 框架中,配置 Bean 的方式主要有两种:XML 配置 和 Java 配置类。这两种方式都可以实现将对象注册到 Spring 容器中,并通过依赖注入进行管理。本文将详细介绍这两种配置方式的步骤,并提供相应的代码示例。 1. 使用 XML 配置的方式 步骤 创建 Spring 配置文件 创建…

海之淀攻略

家长要做的功课 家长可根据孩子情况&#xff0c;需要做好以下功课&#xff1a; 未读小学的家长&#xff1a;了解小学小升初派位初中校额到校在读小学的家长&#xff1a;了解小升初派位初中校额到校在读初中的家长&#xff1a;了解初中校额到校 越是高年级的家长&#xff0c;…

BUUCTF-[GWCTF 2019]re3

[GWCTF 2019]re3 查壳&#xff0c;64位无壳 然后进去发现主函数也比较简单&#xff0c;主要是一个长度校验&#xff0c;然后有一个mprotect函数&#xff0c;说明应该又是Smc&#xff0c;然后我们用脚本还原sub_402219函数处的代码 import idc addr0x00402219 size224 for …

sql server 开启cdc报事务正在执行

今天开启数据库cdc 功能的时候提示&#xff1a;一个dbrole 的存储过程&#xff0c;rolemember cdc db_ower, &#xff0c;有事务正在进行&#xff0c;执行失败。 执行多次仍然如此&#xff0c;开启cdc的存储过程是sys.sp_cdc_enable_db;查询了一下网络&#xff0c;给出的方…

2025年GPLT团体程序设计天梯赛L1-L2

目录 1.珍惜生命 2.偷感好重 3.高温补贴 4.零头就抹了吧 5.这是字符串题 6.这不是字符串题 7.大幂数​编辑 8.现代战争​编辑 9.算式拆解 10.三点共线 11.胖达的山头 12.被n整除的n位数 1.珍惜生命 【解析】直接输出即可 #include<bits/stdc.h> using namespace…

promethus基础

1.下载prometheus并解压 主要配置prometheus.yml文件 在scrape_configs配置项下添加配置(hadoop202是主机名)&#xff1a; scrape_configs: job_name: ‘prometheus’ static_configs: targets: [‘hadoop202:9090’] 添加 PushGateway 监控配置 job_name: ‘pushgateway’…

缓存与数据库数据一致性:旁路缓存、读写穿透和异步写入模式解析

旁路缓存模式、读写穿透模式和异步缓存写入模式是三种常见的缓存使用模式&#xff0c;以下是对三种经典缓存使用模式在缓存与数据库数据一致性方面更全面的分析&#xff1a; 一、旁路缓存模式&#xff08;Cache - Aside Pattern&#xff09; 1.数据读取流程 应用程序首先向缓…

【ESP32S3】 下载时遇到 libusb_open() failed 解决方案

之前写过一篇 《VSCode 开发环境搭建》 的文章&#xff0c;很多小伙伴反馈说在下载固件或者配置的时候会报错&#xff0c;提示大多是 libusb_open() failed ...... &#xff1a; 这其实是由于 USB 驱动不正确导致的&#xff0c;准确来说应该是与 ESP-IDF 中内置的 OpenOCD 需要…

ISCTF2024-misc(部分)

前言 之前写的&#xff0c;一直没发&#xff0c;留个记录吧&#xff0c;万一哪天记录掉了起码在csdn有个念想 1.少女的秘密花园 打开是个图片 随波逐流binwalk一下分离得到一个zip&#xff0c;解压得到base_misc发现是zip 爆破得到密码 解压得到一个txt&#xff0c;将里面的…

word内容使用python替换

拥有一个固定的word文件&#xff0c;类似模板 比如写一个测试计划&#xff0c;大多数内容都是通用&#xff0c;只需要改改软件名称&#xff0c;人员等等&#xff0c;数量多起来的情况下就可以使用代码 # 导入 Document 类&#xff0c;用于处理 Word 文档 from docx import Do…

py语法基础理解

条件判断 只有if-else等我语句,Python不支持switch语句 单if语句 if 条件语句: 条件为真时执行的内容 if-else语句 if 条件语句: 条件为真时执行的内容 else: 条件为假时执行的内容 if-elif语句 else if if 条件语句1: 条件语句1为真时执行的内容 elif 条件语句…

SQL进阶知识:九、高级数据类型

今天介绍下关于高级数据类型的详细介绍&#xff0c;并结合MySQL数据库提供实际例子。 在MySQL中&#xff0c;高级数据类型主要用于处理复杂的数据结构&#xff0c;如JSON、XML和空间数据。这些数据类型提供了更强大的功能&#xff0c;可以满足现代应用程序对数据存储和处理的多…

Linux软硬链接和动静态库(20)

文章目录 前言一、软硬链接基本认知实现原理应用场景取消链接ACM时间 二、动静态库认识库库的作用 三、制作静态库静态库的打包静态库的使用 四、制作动态库动态区的打包动态库的链接与使用动态库的链接原理 总结 前言 我有款非常喜欢玩的游戏&#xff0c;叫做《饥荒》&#xf…

【鸿蒙HarmonyOS】深入理解router与Navigation

5. 路由 1.页面路由(router模式&#xff09; 1.概述 页面路由指的是在应用程序中实现不同页面之间的跳转&#xff0c;以及数据传递。 我们先明确自定义组件和页面的关系&#xff1a; 自定义组件&#xff1a;Component 装饰的UI单元&#xff0c;页面&#xff1a;即应用的UI…

Apache SeaTunnel:新一代开源、高性能数据集成工具

Apache SeaTunnel 是一款开源、分布式、高性能的数据集成工具&#xff0c;可以通过配置快速搭建数据管道&#xff0c;支持实时海量数据同步。 Apache SeaTunnel 专注于数据集成和数据同步&#xff0c;主要旨在解决数据集成领域的常见问题&#xff1a; 数据源多样性&#xff1a…

CF-Hero:自动绕过CDN找真实ip地址

CF-Hero&#xff1a;自动绕过CDN找真实ip地址 CF-Hero 是一个全面的侦察工具&#xff0c;用于发现受 Cloudflare 保护的 Web 应用程序的真实 IP 地址。它通过各种方法执行多源情报收集。目前仅支持Cloudflare的cdn服务查找真实ip&#xff0c;但从原理上来说查找方法都是通用的…

React-组件和props

1、类组件 import React from react; class ClassApp extends React.Component {constructor(props) {super(props);this.state{};}render() {return (<div><h1>这是一个类组件</h1><p>接收父组件传过来的值&#xff1a;{this.props.name}</p>&…

谈谈接口和抽象类有什么区别?

接口&#xff08;interface&#xff09;和抽象类&#xff08;abstract class&#xff09;都是 Java 中常用的“抽象”工具&#xff0c;用来定义类的规范和结构&#xff0c;但它们有一些本质的区别。下面我用一个简单明了的表格 说明来帮你理解&#xff1a; 对比点抽象类&…