1. 程式人生 > 程式設計 >聊聊Spring MVC JSON資料互動的問題

聊聊Spring MVC JSON資料互動的問題

我們在開發中後端經常需要接受來自於前端傳遞的on字串資料,怎麼把Json字串轉換為物件呢?後端也經常需要給前端返回Json字串,怎麼把Java物件資料轉換為Json字串返回呢?

回顧JSON

JSON( Object Notation)

各個JSON技術比較

早期 JSON 的組裝和解析都是通過手動編寫程式碼來實現的,這種方式效率不高,所以後來有許多的關於組裝和解析 JSON 格式資訊的工具類出現,如 json-lib、Jackson、Gson 和 FastsOigJSxpTyJson 等,可以解決 JSON 互動的開發效率。

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 等。

對於複雜型別的轉換,json-lib 在將 JSON 轉換成 Bean 時還有缺陷,比如一個類裡包含另一個類的 List 或者 Map 集合,json-lib 從 JSON 到 Bean 的轉換就會出現問題。

所以 json-lib 在功能和效能上面都不能滿足現在網際網路化的需求。

2)開源的Jackson

開源的 Jackson 是 Spring MVC 內建的 JSON 轉換工具。相比 json-lib 框架,Jackson 所依賴 jar 檔案較少,簡單易用並且效能也要相對高些。並且 Jackson 社群相對比較活躍,更新速度也比較快。

但是 Jackson 對於複雜型別的 JSON 轉換 Bean 會出現問題,一些集合 Map、List 的轉換出現問題。而 Jackson 對於複雜型別的 Bean 轉換 JSON,轉換的 JSON 格式不是標準的 JSON 格式。

3)Google的Gson

Gson 是目前功能最全的 JSON 解析神器,Gson 當初是應 Google 公司內部需求由 Google 自行研發。自從在 2008 年 5 月公開發布第一版後,Gson 就已經被許多公司或使用者應用。

Gson 主要提供了 toJson 與 fromJson 兩個轉換函式,不需要依賴其它的 jar 檔案,就能直接在 JDK 上執行。在使用這兩個函式轉換之前,需要先建立好物件的型別以及其成員才能成功的將 JSON 字串轉換為相對應的物件。

類裡面只要有 get 和 set 方法,Gson 完全可以將複雜型別的 JSON 到 Bean 或 Bean 到 JSON 的轉換,是 JSON 解析的神器。Gson 在功能上面無可挑剔,但效能比 FastJson 有所差距。

4)阿里巴巴的FastJson

FastJson 是用 Java 語言編寫的高效能 JSON 處理器,由阿里巴巴公司開發。

FastJson 不需要依賴其它的 jar 檔案,就能直接在 JDK 上執行。

FastJson 在複雜型別的 Bean 轉換 JSON 上會出現一些問題,可能會出現引用的型別,導致 JSON 轉換出錯,需要制定引用。

FastJson 採用獨創的演算法,將 parse 的速度提升到極致,超過所有 JSON 庫。

綜上 4 種 JSON 技術的比較,在專案選型的時候可以使用 Google 的 Gson 和阿里巴巴的 FastJson 兩種並行使用,如果只是功能要求,沒有效能要求,可以使用Google 的 Gson。如果有效能上面的要求可以使用 Gson 將 Bean 轉換 JSON 確保資料的正確,使用 FastJson 將 JSON 轉換 Bean。

JSON 資料轉換

Spring MVC 在資料繫結的過程中需要對傳遞資料的格式和型別進行轉換,它既可以轉換 String 等型別的資料,也可以轉換 JSON 等其他型別的資料。

開源的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>
       <!--通過初始化引數指定SpringMVC配置檔案的位置,進行關聯-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!-- 啟動順序,數字越小,啟動越早 -->
       <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>

建立POJO類

package com.kuang.pojo;

public class User {
    private String name;
    private int age;
    private String sex;

    /**省略setter和getter方法*/

建立控制器

完成後端Java物件轉換為前端Json字串

@ResponseBody

當返回 POJO 物件時預設轉換為 JSON 格式資料進行響應

在這裡插入圖片描述

這裡我們需要兩個新東西,一個是@ResponseBody,一個是ObjectMapper物件

@RestController(推薦)

返回json字串統一解決

在這裡插入圖片描述
在類上直接使用 @RestController ,這樣子,裡面所有的方法都只會返回 json 字串了,不用再每一個都新增@ResponseBody !我們在前後端分離開發中,一般都使用

執行測試

配置Tomcat執行

在這裡插入圖片描述

解決亂碼

@RequestMaping的produces屬性

//produces:指定響應體返回型別和編碼
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")

如果專案中有許多請求則每一個都要新增

Spring配置統一指定(推薦)

我們可以在springmvc的配置檔案上新增一段訊息StringHttpMessageConverter轉換配置,這樣就不用每次都去處理了

<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&gt;
   </mvc:message-converters>
</mvc:annotation-driven>

在這裡插入圖片描述

測試集合輸出

控制器增加方法

@RestController
public class UserController {

    //produces:指定響應體返回型別和編碼
    @RequestMapping(value = "/json1")
    public String json1() throws JsonProcessingException {
        //建立一個jackson的物件對映器,用來解析資料
        ObjectMapper mappwww.cppcns.comer = new ObjectMapper();
        //建立一個物件
        User user = new User("秦疆1號",3,"男");
        //將我們的物件解析成為json格式
        String str = mapper.writeValueAsString(user);
        //由於@ResponseBody註解,這裡會將str轉成json格式返回;十分方便
        return str;
    }

    @RequestMapping("/json2")
    public String json2() throws JsonProcessingException {

        //建立一個jackson的物件對映器,用來解析資料
        ObjectMapper mapper = new ObjectMapper();
        //建立一個物件
        User user1 = new User("秦疆1號","男");
        User user2 = new User("秦疆2號","男");
        User user3 = new User("秦疆3號","男");
        User user4 = new User("秦疆4號","男");
        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;
    }

}

在這裡插入圖片描述

輸出時間物件

增加一個新的方法

在這裡插入圖片描述
在這裡插入圖片描述

預設日期格式會變成一個數字,是1970年1月1日到當前日期的毫秒數!

Jackson 預設是會把時間轉成timestamps形式

自定義時間格式

在這裡插入圖片描述
在這裡插入圖片描述

抽取為工具類

如果要經常使用的話,這樣是比較麻煩的,我們可以將這些程式碼封裝到一個工具類中;我們去編寫下

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();
 www.cppcns.com      //不使用時間差的方式
       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是阿里開發的一款專門用於Java開發的包,可以方便的實現json物件與JavaBean物件的轉換,實現JavaBean物件與json字串的轉換,實現json物件與json字串的轉換。實現json的轉換方法很多,最後的實現結果都是一樣的。

這種工具類,我們只需要掌握使用就好了,在使用的時候在根據具體的業務去找對應的實現。和以前的commons-io那種工具包一樣,拿來用就好了!

fastjson 三個主要的類

JSON代表 JSONObject和JSONArray的轉化

  • JSON類原始碼分析與使用
  • 仔細觀察這些方法,主要是實現json物件,json物件陣列,javabean物件,json字串之間的相互轉化。

JSONObject 代表 json 物件

  • JSONObject實現了Map介面,猜想 JSONObject底層操作是由Map實現的。
  • JSONObject對應json物件,通過各種形式的get()方法可以獲取json物件中的資料,也可利用諸如size(),isEmpty()等方法獲取"鍵:值"對的個數和判斷是否為空。其本質是通過實現Map介面並呼叫介面中的方法完成的。

JSONArray 代表 json 物件陣列

內部是有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) {
       //建立一個物件
       User user1 = new User("秦疆1號","男");
       User user2 = new User("秦疆2號","男");
       User user3 = new User("秦疆3號","男");
       User user4 = new User("秦疆4號","男");
       List<User> list = new ArrayList<User>();
       list.add(user1);
       list.add(user2);
       list.add(user3);
       list.add(user4);

       System.out.println("*******Java物件 轉 JSON字串*******");
     http://www.cppcns.com  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字串 轉 Java物件*******");
       User jp_user1=JSON.parseObject(str2,User.class);
       System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);

       System.out.println("\n****** Java物件 轉 JSON物件 ******");
       JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
       System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));

       System.out.println("\n****** JSON物件 轉 Java物件 ******");
       User to_java_user = JSON.toJavaObject(jsonObject1,User.class);
       System.out.println("JSON.toJavaObject(jsonObject1,User.class)==>"+to_java_user);
  }
}

到此這篇關於Spring MVC JSON資料互動的文章就介紹到這了,更多相關Spring MVC JSON資料互動內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!