聊聊Spring MVC JSON數(shù)據(jù)交互的問題
我們在開發(fā)中后端經(jīng)常需要接受來自于前端傳遞的Json字符串數(shù)據(jù),怎么把Json字符串轉(zhuǎn)換為Java對象呢?后端也經(jīng)常需要給前端返回Json字符串,怎么把Java對象數(shù)據(jù)轉(zhuǎn)換為Json字符串返回呢?
回顧JSON
JSON(JavaScript Object Notation)
各個JSON技術比較
早期 JSON 的組裝和解析都是通過手動編寫代碼來實現(xiàn)的,這種方式效率不高,所以后來有許多的關于組裝和解析 JSON 格式信息的工具類出現(xiàn),如 json-lib、Jackson、Gson 和 FastJson 等,可以解決 JSON 交互的開發(fā)效率。
1)json-lib
json-lib 最早也是應用廣泛的 JSON 解析工具,缺點是依賴很多的第三方包,如 commons-beanutils.jar、commons-collections-3.2.jar、commons-lang-2.6.jar、commons-logging-1.1.1.jar、ezmorph-1.0.6.jar 等。
對于復雜類型的轉(zhuǎn)換,json-lib 在將 JSON 轉(zhuǎn)換成 Bean 時還有缺陷,比如一個類里包含另一個類的 List 或者 Map 集合,json-lib 從 JSON 到 Bean 的轉(zhuǎn)換就會出現(xiàn)問題。
所以 json-lib 在功能和性能上面都不能滿足現(xiàn)在互聯(lián)網(wǎng)化的需求。
2)開源的Jackson
開源的 Jackson 是 Spring MVC 內(nèi)置的 JSON 轉(zhuǎn)換工具。相比 json-lib 框架,Jackson 所依賴 jar 文件較少,簡單易用并且性能也要相對高些。并且 Jackson 社區(qū)相對比較活躍,更新速度也比較快。
但是 Jackson 對于復雜類型的 JSON 轉(zhuǎn)換 Bean 會出現(xiàn)問題,一些集合 Map、List 的轉(zhuǎn)換出現(xiàn)問題。而 Jackson 對于復雜類型的 Bean 轉(zhuǎn)換 JSON,轉(zhuǎn)換的 JSON 格式不是標準的 JSON 格式。
3)Google的Gson
Gson 是目前功能最全的 JSON 解析神器,Gson 當初是應 Google 公司內(nèi)部需求由 Google 自行研發(fā)。自從在 2008 年 5 月公開發(fā)布第一版后,Gson 就已經(jīng)被許多公司或用戶應用。
Gson 主要提供了 toJson 與 fromJson 兩個轉(zhuǎn)換函數(shù),不需要依賴其它的 jar 文件,就能直接在 JDK 上運行。在使用這兩個函數(shù)轉(zhuǎn)換之前,需要先創(chuàng)建好對象的類型以及其成員才能成功的將 JSON 字符串轉(zhuǎn)換為相對應的對象。
類里面只要有 get 和 set 方法,Gson 完全可以將復雜類型的 JSON 到 Bean 或 Bean 到 JSON 的轉(zhuǎn)換,是 JSON 解析的神器。Gson 在功能上面無可挑剔,但性能比 FastJson 有所差距。
4)阿里巴巴的FastJson
FastJson 是用 Java 語言編寫的高性能 JSON 處理器,由阿里巴巴公司開發(fā)。
FastJson 不需要依賴其它的 jar 文件,就能直接在 JDK 上運行。
FastJson 在復雜類型的 Bean 轉(zhuǎn)換 JSON 上會出現(xiàn)一些問題,可能會出現(xiàn)引用的類型,導致 JSON 轉(zhuǎn)換出錯,需要制定引用。
FastJson 采用獨創(chuàng)的算法,將 parse 的速度提升到極致,超過所有 JSON 庫。
綜上 4 種 JSON 技術的比較,在項目選型的時候可以使用 Google 的 Gson 和阿里巴巴的 FastJson 兩種并行使用,如果只是功能要求,沒有性能要求,可以使用Google 的 Gson。如果有性能上面的要求可以使用 Gson 將 Bean 轉(zhuǎn)換 JSON 確保數(shù)據(jù)的正確,使用 FastJson 將 JSON 轉(zhuǎn)換 Bean。
JSON 數(shù)據(jù)轉(zhuǎn)換
Spring MVC 在數(shù)據(jù)綁定的過程中需要對傳遞數(shù)據(jù)的格式和類型進行轉(zhuǎn)換,它既可以轉(zhuǎn)換 String 等類型的數(shù)據(jù),也可以轉(zhuǎn)換 JSON 等其他類型的數(shù)據(jù)。
開源的Jackson
新建一個module ,springmvc-05-json , 添加web的支持
導入jar文件
Maven 項目在 pom.xml 文件中添加以下依賴。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency>
配置Spring MVC核心配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.注冊servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通過初始化參數(shù)指定SpringMVC配置文件的位置,進行關聯(lián)-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 啟動順序,數(shù)字越小,啟動越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有請求都會被springmvc攔截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
</web-app>
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自動掃描指定的包,下面所有注解類交給IOC容器管理 -->
<context:component-scan base-package="com.kuang.controller"/>
<!-- 視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前綴 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后綴 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
創(chuàng)建POJO類
package com.kuang.pojo;
public class User {
private String name;
private int age;
private String sex;
/**省略setter和getter方法*/
創(chuàng)建控制器
完成后端Java對象轉(zhuǎn)換為前端Json字符串
@ResponseBody
當返回 POJO 對象時默認轉(zhuǎn)換為 JSON 格式數(shù)據(jù)進行響應

這里我們需要兩個新東西,一個是@ResponseBody,一個是ObjectMapper對象
@RestController(推薦)
返回json字符串統(tǒng)一解決

在類上直接使用 @RestController ,這樣子,里面所有的方法都只會返回 json 字符串了,不用再每一個都添加@ResponseBody !我們在前后端分離開發(fā)中,一般都使用
運行測試
配置Tomcat運行

解決亂碼
@RequestMaping的produces屬性
//produces:指定響應體返回類型和編碼 @RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")
如果項目中有許多請求則每一個都要添加
Spring配置統(tǒng)一指定(推薦)
我們可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter轉(zhuǎn)換配置,這樣就不用每次都去處理了
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

測試集合輸出
控制器增加方法
@RestController
public class UserController {
//produces:指定響應體返回類型和編碼
@RequestMapping(value = "/json1")
public String json1() throws JsonProcessingException {
//創(chuàng)建一個jackson的對象映射器,用來解析數(shù)據(jù)
ObjectMapper mapper = new ObjectMapper();
//創(chuàng)建一個對象
User user = new User("秦疆1號", 3, "男");
//將我們的對象解析成為json格式
String str = mapper.writeValueAsString(user);
//由于@ResponseBody注解,這里會將str轉(zhuǎn)成json格式返回;十分方便
return str;
}
@RequestMapping("/json2")
public String json2() throws JsonProcessingException {
//創(chuàng)建一個jackson的對象映射器,用來解析數(shù)據(jù)
ObjectMapper mapper = new ObjectMapper();
//創(chuàng)建一個對象
User user1 = new User("秦疆1號", 3, "男");
User user2 = new User("秦疆2號", 3, "男");
User user3 = new User("秦疆3號", 3, "男");
User user4 = new User("秦疆4號", 3, "男");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
//將我們的對象解析成為json格式
String str = mapper.writeValueAsString(list);
return str;
}
}

輸出時間對象
增加一個新的方法


默認日期格式會變成一個數(shù)字,是1970年1月1日到當前日期的毫秒數(shù)!
Jackson 默認是會把時間轉(zhuǎn)成timestamps形式
自定義時間格式


抽取為工具類
如果要經(jīng)常使用的話,這樣是比較麻煩的,我們可以將這些代碼封裝到一個工具類中;我們?nèi)ゾ帉懴?/p>
package com.kuang.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
public static String getJson(Object object) {
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
public static String getJson(Object object,String dateFormat) {
ObjectMapper mapper = new ObjectMapper();
//不使用時間差的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定義日期格式對象
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
//指定日期格式
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}

我們使用工具類,代碼就更加簡潔了!
阿里巴巴的FastJson
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.60</version> </dependency>
fastjson.jar是阿里開發(fā)的一款專門用于Java開發(fā)的包,可以方便的實現(xiàn)json對象與JavaBean對象的轉(zhuǎn)換,實現(xiàn)JavaBean對象與json字符串的轉(zhuǎn)換,實現(xiàn)json對象與json字符串的轉(zhuǎn)換。實現(xiàn)json的轉(zhuǎn)換方法很多,最后的實現(xiàn)結(jié)果都是一樣的。
這種工具類,我們只需要掌握使用就好了,在使用的時候在根據(jù)具體的業(yè)務去找對應的實現(xiàn)。和以前的commons-io那種工具包一樣,拿來用就好了!
fastjson 三個主要的類
JSON代表 JSONObject和JSONArray的轉(zhuǎn)化
- JSON類源碼分析與使用
- 仔細觀察這些方法,主要是實現(xiàn)json對象,json對象數(shù)組,javabean對象,json字符串之間的相互轉(zhuǎn)化。
JSONObject 代表 json 對象
- JSONObject實現(xiàn)了Map接口, 猜想 JSONObject底層操作是由Map實現(xiàn)的。
- JSONObject對應json對象,通過各種形式的get()方法可以獲取json對象中的數(shù)據(jù),也可利用諸如size(),isEmpty()等方法獲取"鍵:值"對的個數(shù)和判斷是否為空。其本質(zhì)是通過實現(xiàn)Map接口并調(diào)用接口中的方法完成的。
JSONArray 代表 json 對象數(shù)組
內(nèi)部是有List接口中的方法來完成操作的。
代碼實例
package com.kuang.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kuang.pojo.User;
import java.util.ArrayList;
import java.util.List;
public class FastJsonDemo {
public static void main(String[] args) {
//創(chuàng)建一個對象
User user1 = new User("秦疆1號", 3, "男");
User user2 = new User("秦疆2號", 3, "男");
User user3 = new User("秦疆3號", 3, "男");
User user4 = new User("秦疆4號", 3, "男");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
System.out.println("*******Java對象 轉(zhuǎn) JSON字符串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** JSON字符串 轉(zhuǎn) Java對象*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n****** Java對象 轉(zhuǎn) JSON對象 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("\n****** JSON對象 轉(zhuǎn) Java對象 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
}
}
到此這篇關于Spring MVC JSON數(shù)據(jù)交互的文章就介紹到這了,更多相關Spring MVC JSON數(shù)據(jù)交互內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java replaceAll()方法報錯Illegal group reference的解決辦法
這篇文章主要給大家介紹了關于Java replaceAll()方法報錯Illegal group reference的解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09
Java Lambda List轉(zhuǎn)Map代碼實例
這篇文章主要介紹了Java Lambda List轉(zhuǎn)Map代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03
JAVA對象中使用?static?和?String?基礎探究
這篇文章主要介紹了JAVA對象中使用static和String基礎探究,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09

