Spring如何从客户端接收json数据以及如何发送json数据到客户端(一)

Spring JSON交互详解
本文介绍如何在Spring框架中使用JSON进行数据交互,包括接收和发送JSON数据的具体操作方法及注意事项。

        首先,Spring是没有自带json转换数据的包的,所有我们要自己导入json的包到类路径下,假如是使用Maven的话可以加入以下语句到pom.xml中,还有如果你是使用SpringBoot的话不用加json的包,SpringBoot 默认会使用 Json 作为响应报文格式。(我下面是选用springboot做的,因为最近在学习springboot)

        Maven的添加包(采用gson的包)

 <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>    
       1、使用Spring接收json数据,要实现这点不难,只要在对应的形参对象上使用注解@RequestBody就可以了,例如
public class User {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
然后在控制器的相应的方法的参数类型前使用@RequestBody
public User Post(@RequestBody  User user, HttpServletRequest httpServeltRequest, HttpServletResponse httpServletResponse) throws IOException {
        System.out.println(user);
        return user;
    }

注意,@RequestBody一定要在形参对象的类型前面,注意,Spring会调用类路径下的json包,但是它会根据json传递的键名和变量的域的名字进行匹配,而且还必须得有get和set(javaBean)的方法。例如一旦你这里把username写成UserName,json将解析不出来。

        一旦匹配成功,spring将自动把json中的参数赋值到对象中来。

        2、使用Spring发送json参数,对于这点,有两个方法,一是使用@ResponseBody,二是使用@RestController

@RequestMapping(method = RequestMethod.POST)
    public @ResponseBody User Post(@RequestBody  User user, HttpServletRequest httpServeltRequest, HttpServletResponse httpServletResponse) throws IOException {
        System.out.println(user);
        return user;
    }

@ResponseBody放在方法返回类型的前面,当加上@ResponseBody的时候,Spring会跳过正常的MVC流程,转而直接将数据以特定的形式发送的到客户端(可能是根据请求头中的数据类型)

        第二种是采用将@Controller改成@RestController的形式

@Controller
@RequestMapping("/json")
public class JsonController {

    @RequestMapping(method = RequestMethod.POST)
    public User Post(@RequestBody  User user, HttpServletRequest httpServeltRequest, HttpServletResponse httpServletResponse) throws IOException {
        System.out.println(user);
        return user;
    }
}
这样的效果跟@ResponseBody一样,但是不同的是这个类(JsonController )下面的全部方法都变成非正常MVC的形式,所以两种方式要选择性使用
  
<think>我们使用Spring Boot来接收客户端传来的JSON数据并反序列化为Java对象。Spring Boot默认使用Jackson库来处理JSON的序列化和反序列化。以下是实现的步骤: 1. **添加依赖**:Spring Boot Web starter已经包含了Jackson,所以通常不需要额外添加依赖。 2. **创建Controller**:使用`@RestController`注解的类来处理HTTP请求。 3. **定义数据模型**:创建Java类来表示要反序列化的JSON数据结构。 4. **使用`@RequestBody`注解**:在Controller的方法参数上使用`@RequestBody`注解,Spring会自动将传入的JSON数据反序列化为对应的Java对象。 ### 步骤1: 添加依赖(如果尚未添加) 在`pom.xml`中确保有Spring Boot Web依赖: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> ``` ### 步骤2: 定义数据模型 创建个Java类,其属性与JSON字段对应。例如,假设客户端发送JSON数据如下: ```json { "name": "张三", "age": 25 } ``` 则对应的Java类为: ```java public class UserData { private String name; private int age; // 必须有无参构造函数(Jackson反序列化需要) public UserData() { } // Getter和Setter方法 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; } } ``` ### 步骤3: 创建Controller处理请求 在Controller中,使用`@PostMapping`(其他HTTP方法映射注解)来指定接收请求的路径,并在方法参数中使用`@RequestBody`来接收JSON数据并自动反序列化。 ```java import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @PostMapping("/user") public String createUser(@RequestBody UserData userData) { // 这里userData已经是反序列化后的Java对象 System.out.println("用户名: " + userData.getName()); System.out.println("年龄: " + userData.getAge()); // 处理业务逻辑... return "用户创建成功"; } } ``` ### 关键点说明 - **`@RequestBody`**:这个注解告诉Spring将HTTP请求体(JSON数据)反序列化为个`UserData`对象[^1]。 - **字段匹配**:JSON中的字段名必须与Java类中的属性名致(者通过注解指定映射关系,如`@JsonProperty`)[^3]。 - **无参构造函数**:Jackson在反序列化时需要无参构造函数(如果类中没有定义任何构造函数,Java会默认提供无参构造;如果定义了带参构造,必须显式添加无参构造)[^1]。 - **Getter和Setter**:虽然Jackson可以直接访问字段,但提供Getter和Setter是推荐的做法(特别是需要序列化时)[^1]。 ### 自定义反序列化 如果需要对某些字段进行特殊处理(如日期格式、自定义逻辑),可以使用Jackson的注解自定义反序列化器[^5]。 #### 示例:使用`@JsonFormat`处理日期 假设JSON中包含日期字段: ```json { "name": "张三", "age": 25, "birthday": "1990-01-01" } ``` 在Java类中: ```java public class UserData { private String name; private int age; @JsonFormat(pattern = "yyyy-MM-dd") private Date birthday; // 省略其他代码 } ``` #### 示例:自定义反序列化器 当默认行为无法满足需求时,可以自定义反序列化器。例如,将字符串"男""女"反序列化为枚举`Gender`: ```java public enum Gender { MALE, FEMALE } ``` 自定义反序列化器: ```java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; public class GenderDeserializer extends JsonDeserializer<Gender> { @Override public Gender deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String text = p.getText(); if ("男".equals(text)) { return Gender.MALE; } else if ("女".equals(text)) { return Gender.FEMALE; } throw new IllegalArgumentException("无效的性别值"); } } ``` 在字段上使用自定义反序列化器: ```java public class UserData { private String name; private int age; @JsonDeserialize(using = GenderDeserializer.class) private Gender gender; // 省略其他代码 } ``` ### 测试 使用Postmancurl发送POST请求: - URL: `http://localhost:8080/user` - Body (JSON): ```json { "name": "张三", "age": 25 } ``` ### 注意事项 - **JSON字段与Java属性匹配**:默认情况下,Jackson通过字段名匹配。如果JSON字段名与Java属性名不致,可以使用`@JsonProperty`注解: ```java @JsonProperty("full_name") private String fullName; ``` - **忽略未知字段**:默认情况下,如果JSON中有Java类不存在的字段,Jackson会抛出异常。可以通过在类上添加`@JsonIgnoreProperties(ignoreUnknown = true)`来忽略未知字段[^3]: ```java @JsonIgnoreProperties(ignoreUnknown = true) public class UserData { // ... } ``` - **集合类型**:也可以反序列化为集合类型,如`List<UserData>`: ```java @PostMapping("/users") public String createUsers(@RequestBody List<UserData> users) { // ... } ``` 通过以上步骤,Spring Boot可以轻松接收并反序列化客户端传来的JSON数据。 ### 相关问题 1. 如何在Spring Boot中自定义JSON序列化和反序列化规则? 2. Spring Boot如何处理JSON数据中的日期格式? 3. 在Spring Boot中如何忽略JSON中的未知字段? 4. 如何验证反序列化后的对象数据(如使用Hibernate Validator)?</think>### 在Spring Boot中接收JSON数据并反序列化的实现 Spring Boot提供了强大的JSON处理能力,默认使用Jackson库进行序列化和反序列化操作。以下是完整实现步骤: #### 1. 添加依赖(确保pom.xml包含) ```xml <dependencies> <!-- Spring Web MVC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Jackson核心库(通常已包含在web中) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies> ``` #### 2. 创建数据模型类 ```java public class UserData { private String name; private int age; // 必须有无参构造函数 public UserData() {} // Getter和Setter方法(Jackson通过反射访问) 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; } } ``` #### 3. 创建Controller接收请求 ```java import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { // 使用@RequestBody自动反序列化JSON @PostMapping("/users") public String createUser(@RequestBody UserData userData) { System.out.println("接收用户: " + userData.getName() + ", 年龄: " + userData.getAge()); return "用户创建成功"; } } ``` #### 4. 自定义序列化/反序列化(可选) 当需要特殊处理字段时,可使用Jackson注解: ```java import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; public class CustomUser { @JsonProperty("user_name") // JSON字段重命名 private String name; @JsonIgnore // 忽略此字段 private String password; @JsonFormat(pattern = "yyyy-MM-dd") // 日期格式化 private Date birthDate; // Getter/Setter省略 } ``` #### 5. 使用ObjectMapper手动处理 需要精细控制时直接使用ObjectMapper: ```java import com.fasterxml.jackson.databind.ObjectMapper; @RestController public class ManualController { @PostMapping("/manual") public String manualDeserialize(@RequestBody String json) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); UserData user = objectMapper.readValue(json, UserData.class); // 处理复杂类型 Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {}); return "处理成功"; } } ``` #### 6. 测试请求示例 使用curl测试: ```bash curl -X POST http://localhost:8080/users \ -H "Content-Type: application/json" \ -d '{"name":"张三", "age":25}' ``` #### 关键点说明 1. **`@RequestBody`注解**:自动将请求体中的JSON反序列化为Java对象[^1] 2. **字段匹配规则**:JSON属性名默认与Java字段名匹配(大小写不敏感) 3. **日期处理**:使用`@JsonFormat`定义日期格式[^3] 4. **忽略字段**:`@JsonIgnore`跳过序列化/反序列化[^3] 5. **类型安全**:复杂泛型使用`TypeReference`[^1] 6. **错误处理**:添加全局异常处理器捕获反序列化错误 #### 完整Controller示例 ```java @RestController public class UserController { @PostMapping("/users") public ResponseEntity<String> createUser(@Valid @RequestBody UserData userData) { // 业务处理逻辑 return ResponseEntity.ok("用户创建成功: " + userData.getName()); } // 全局异常处理 @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity<String> handleJsonError() { return ResponseEntity.badRequest().body("JSON格式错误"); } } ``` ### 常见问题解决方案 1. **字段不匹配问题**: - 使用`@JsonProperty("json_field")`显式映射 - 在application.properties中配置: ```properties spring.jackson.property-naming-strategy=SNAKE_CASE ``` 2. **日期格式处理**: ```java public class User { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date registerTime; } ``` 3. **忽略未知字段**: ```java @JsonIgnoreProperties(ignoreUnknown = true) public class UserData { // ... } ``` 4. **自定义序列化器**: ```java public class MoneySerializer extends JsonSerializer<BigDecimal> { @Override public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider provider) { gen.writeString(value.setScale(2) + "元"); } } public class Product { @JsonSerialize(using = MoneySerializer.class) private BigDecimal price; } ``` ### 性能优化建议 1. 重用ObjectMapper实例(Spring默认单例) 2. 对于大文件流式处理: ```java JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createParser(inputStream); while (parser.nextToken() != null) { // 流式处理 } ``` 通过以上实现,Spring Boot可以高效接收并反序列化客户端传来的JSON数据[^1][^3][^5]。 --- ### 相关问题 1. 如何在Spring Boot中自定义JSON字段的命名策略? 2. 如何处理JSON中的日期/时间格式转换问题? 3. 如何为特定字段实现自定义的序列化/反序列化逻辑? 4. 在微服务架构中如何确保多个服务间的JSON数据兼容性?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值