連JSON的使用你都沒精通,你還說對自己的Java很自信舞虱?

什么是JSON?

  • JSON(JavaScript Object Notation, NS對象標(biāo)記)是一種輕量級的數(shù)據(jù)交換格式欢际,目前使用特別廣泛。
  • 采用完全獨(dú)立于編程語言的文本格式來存儲和表示數(shù)據(jù)矾兜。
  • 簡潔和清晰的層次結(jié)構(gòu)使得JSON成為理想的數(shù)據(jù)交換語言损趋。
  • 易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率浑槽。

在JavaScript語言中蒋失,一切都是對象。因此桐玻,任何JavaScript 支持的類型都可以通過JSON來表示篙挽,例如字符串、數(shù)字镊靴、對象铣卡、數(shù)組等∑梗看看他的要求和語法格式:

  • 對象表示為鍵值對煮落,數(shù)據(jù)由逗號分隔
  • 花括號保存對象
  • 方括號保存數(shù)組

JSON鍵值對是用來保存JavaScript對象的一種方式,和JavaScript對象的寫法也大同小異踊谋,鍵/值對組合中的鍵名寫在前面并用雙引號 “” 包裹蝉仇,使用冒號 : 分隔,然后緊接著值:

{"name":"zhangsan"}
{"age":"3"}
{"sex":"男"}
  • JSON是JavaScript對象的字符串表示法殖蚕,它使用文本表示一個(gè)JS對象的信息轿衔,本質(zhì)是一個(gè)字符串。
var obj = {a:'Hello',b:'World'};//這是一個(gè)對象睦疫,注意鍵名也是可以使用引號包裹的
var json = '{a:"Hello",b:"World"}';//這是一個(gè)JSON字符串害驹,本質(zhì)是一個(gè)字符串

JSON和 JavaScript 對象互轉(zhuǎn)

  • 要實(shí)現(xiàn)從JSON字符串轉(zhuǎn)換為JavaScript對象,使用JSON.parse()方法:
var obj = JSON.parse('{a:"Hello",b:"World"}');
//結(jié)果是 {a:'Hello',b:'World'}
  • 要實(shí)現(xiàn)從JavaScript對象轉(zhuǎn)化為JSON字符串笼痛,使用JSON.stringify()方法:
var json = JSON.stringify({a:'Hello',b:'World'});
//結(jié)果是 '{a:"Hello",b:"World"}'

代碼測試

  1. 新建一個(gè)module裙秋,spring-05-json,添加web支持
  2. 在web目錄下新建一個(gè)jsontest.html缨伊,編寫測試內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script type="text/javascript">
        //編寫一個(gè)JavaScript對象
        var user={
            name:"張三",
            age:3,
            sex:"男"
        };
        console.log(user);

        //將 js 對象轉(zhuǎn)換為 json 對象;
        var json = JSON.stringify(user);
        console.log(json);

        //將 json 對象轉(zhuǎn)換為 js 對象进宝;
        var obj = JSON.parse(json);
        console.log(obj);
    </script>
</head>
<body>

</body>
</html>
  1. 在IDEA中使用瀏覽器打開刻坊,查看控制臺輸出。
image

Controller返回 JSON數(shù)據(jù)

  • Jackson應(yīng)該是目前比較好的json解析工具了
  • 當(dāng)然工具不止這一個(gè)党晋,比如還有阿里巴巴的 fastjson 等等谭胚。
  • 我們這里使用 Jackson,使用它需要導(dǎo)入它的jar包未玻。

Jackson

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.9</version>
</dependency>
  • 配置SpringMVC需要的配置文件

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配置文件的位置灾而,進(jìn)行關(guān)聯(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.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--自動掃描包旁趟,讓指定包下的注解生效,有IOC容器統(tǒng)一管理-->
    <context:component-scan base-package="com.kuang.controller"/>

    <!--讓springmvc 不處理靜態(tài)資源-->
    <mvc:default-servlet-handler/>

    <!--開啟注解支持-->
    <mvc:annotation-driven/>

    <!--配置視圖解析器-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前綴解析器-->
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <!--后綴解析器-->
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>
  • 編寫一個(gè)User實(shí)體類
//需要導(dǎo)入lombok
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
    private String sex;
}
  • 編寫一個(gè)測試類Controller
@Controller
public class UserController {
    @RequestMapping("/json1")
    @ResponseBody //他就不去走視圖解析器庇绽,直接返回一個(gè)字符串
    public String json1() throws Exception{
        //jackson
        ObjectMapper mapper =new ObjectMapper();

        User user = new User("張三01",21,"男");
        String str = mapper.writeValueAsString(user);
        return str;
    }
}

配置Tomcat 锡搜, 啟動測試一下橙困!

http://localhost:8080/json1

image

發(fā)現(xiàn)出現(xiàn)了亂碼問題,我們需要設(shè)置一下他的編碼格式為utf-8耕餐,以及它返回的類型凡傅;

通過@RequestMapping的produces屬性來實(shí)現(xiàn),修改下代碼:

//沒有在配置文件中配置肠缔,可以單個(gè)解決亂碼
//produces:指定響應(yīng)體返回類型和編碼
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")

再次測試夏跷, http://localhost:8080/json1 , 亂碼問題OK明未!

image

亂碼統(tǒng)一解決

上一種方法比較麻煩槽华,如果項(xiàng)目中有許多請求則每一個(gè)都要添加,可以通過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>

返回json字符串統(tǒng)一解決

在類上直接使用 @RestController 煮纵,這樣子懂鸵,里面所有的方法都只會返回 json 字符串了,不用再每一個(gè)都添加@ResponseBody 行疏!我們在前后端分離開發(fā)中匆光,一般都使用 @RestController ,十分便捷酿联!

@RestController
public class UserController {

   //produces:指定響應(yīng)體返回類型和編碼
   @RequestMapping(value = "/json1")
   public String json1() throws JsonProcessingException {
       //創(chuàng)建一個(gè)jackson的對象映射器终息,用來解析數(shù)據(jù)
       ObjectMapper mapper = new ObjectMapper();
       //創(chuàng)建一個(gè)對象
       User user = new User("張三1號", 3, "男");
       //將我們的對象解析成為json格式
       String str = mapper.writeValueAsString(user);
       //由于@ResponseBody注解,這里會將str轉(zhuǎn)成json格式返回贞让;十分方便
       return str;
  }

}

啟動tomcat測試周崭,結(jié)果都正常輸出!

測試集合輸出

增加一個(gè)新的方法

@RequestMapping("/json2")
@ResponseBody //他就不去走視圖解析器喳张,直接返回一個(gè)字符串
public String json2() throws Exception{

    //jackson
    ObjectMapper mapper =new ObjectMapper();

    List<User> userList = new ArrayList<User>();

    User user1 = new User("張三01",21,"男");
    User user2 = new User("張三02",21,"男");
    User user3 = new User("張三03",21,"男");
    User user4 = new User("張三04",21,"男");

    userList.add(user1);
    userList.add(user2);
    userList.add(user3);
    userList.add(user4);

    String str = mapper.writeValueAsString(userList);
    return str;
}

運(yùn)行結(jié)果 : 沒有任何問題续镇!

image

輸出時(shí)間對象

增加一個(gè)新的方法

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

   ObjectMapper mapper = new ObjectMapper();

   //創(chuàng)建時(shí)間一個(gè)對象,java.util.Date
   Date date = new Date();
   //將我們的對象解析成為json格式
   String str = mapper.writeValueAsString(date);
   return str;
}

運(yùn)行結(jié)果 :

image
  • 默認(rèn)日期格式會變成一個(gè)數(shù)字销部,是1970年1月1日到當(dāng)前日期的毫秒數(shù)摸航!
  • Jackson 默認(rèn)是會把時(shí)間轉(zhuǎn)成timestamps形式

解決方案一:使用SimpleDateFormat,自定義時(shí)間格式

@RequestMapping("/json3")
@ResponseBody //他就不去走視圖解析器舅桩,直接返回一個(gè)字符串
public String json3() throws Exception {
  //jackson
  ObjectMapper mapper = new ObjectMapper();

  Date date = new Date();

  //自定義日期格式
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

  return mapper.writeValueAsString(sdf.format(date));
}

解決方案二:取消timestamps形式 酱虎, 自定義時(shí)間格式

@RequestMapping("/json4")
@ResponseBody //他就不去走視圖解析器,直接返回一個(gè)字符串
public String json4() throws Exception {
  //jackson
  ObjectMapper mapper = new ObjectMapper();

  //不使用時(shí)間戳的方式擂涛、
  mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
  //自定義日期格式
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  mapper.setDateFormat(sdf);

  Date date = new Date();
  return mapper.writeValueAsString(date);
}

運(yùn)行結(jié)果 : 成功的輸出了時(shí)間读串!

image

抽取成工具類

如果要經(jīng)常使用的話,這樣是比較麻煩的,我們可以將這些代碼封裝到一個(gè)工具類中爹土;我們?nèi)ゾ帉懴?/strong>

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){
        //jackson
        ObjectMapper mapper = new ObjectMapper();

        //不使用時(shí)間戳的方式
        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;
    }

}

此時(shí)的代碼更加簡潔甥雕。

@RequestMapping("/json5")
@ResponseBody //他就不去走視圖解析器,直接返回一個(gè)字符串
public String json5() throws Exception {
  Date date = new Date();
  return JSONUtils.getJson(date,"yyyy-MM-dd HH:mm:ss");
}

FastJson

fastjson.jar是阿里開發(fā)的一款專門用于Java開發(fā)的包胀茵, 可以方便的實(shí)現(xiàn)json對象與JavaBean對象的轉(zhuǎn)換社露,實(shí)現(xiàn)JavaBean對象與json字符串的轉(zhuǎn)換,實(shí)現(xiàn)json對象 與json字符串的轉(zhuǎn)換琼娘。實(shí)現(xiàn)json的轉(zhuǎn)換方法很多峭弟,最后的實(shí)現(xiàn)結(jié)果都是一樣的。

導(dǎo)入pom依賴

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.20</version>
</dependency>

fastjson三個(gè)主要的類:

  • 【JSONObject代表json對象】 JSONObject實(shí)現(xiàn)了Map接口脱拼,猜想JSONObject底層操作是由Map實(shí)現(xiàn)的瞒瘸。 JSONObject對應(yīng) json對象,通過各種形式的get()方法可以獲取json對象中的數(shù)據(jù)熄浓,也可利用諸如size()情臭,isEmpty()等方法獲取"鍵: 值"對的個(gè)數(shù)和判斷是否為空。其本質(zhì)是通過實(shí)現(xiàn)Map接口并調(diào)用接口中的方法完成的赌蔑。
  • 【JSONArray代表json對象數(shù)組】 內(nèi)部是有List接口中的方法來完成操作的俯在。
  • 【JSON代表JSONObject和 JSONArray的轉(zhuǎn)化】 JSON類源碼分析與使用。 仔細(xì)觀察這些方法娃惯,主要是實(shí)現(xiàn)json對象跷乐,json對象數(shù)組,javabean對象趾浅,json字符串之間的相互轉(zhuǎn)化愕提。

代碼測試:

@RequestMapping("/json6")
@ResponseBody
public String json6() throws Exception {
  List<User> userList = new ArrayList<User>();
  User user1 = new User("張三01",21,"男");
  User user2 = new User("張三02",21,"男");
  User user3 = new User("張三03",21,"男");
  User user4 = new User("張三04",21,"男");
  userList.add(user1);
  userList.add(user2);
  userList.add(user3);
  userList.add(user4);

  System.out.println("****Java對象 轉(zhuǎn) JSON字符串****");
  String str1 = JSON.toJSONString(userList);
  System.out.println(str1);
  String str2 = JSON.toJSONString(user1);
  System.out.println(str2);

  System.out.println("****JSON字符串 轉(zhuǎn) Java對象****");
  User jp_user1 = JSON.parseObject(str2, User.class);
  System.out.println(jp_user1);

  System.out.println("****Java對象 轉(zhuǎn) JSON對象****");
  JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
  System.out.println(jsonObject1.getString("name"));

  System.out.println("****JSON對象 轉(zhuǎn) Java對象****");
  User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
  System.out.println(to_java_user);

  return "Hello";
}

作者:程序員匡胤
鏈接:https://juejin.im/post/6855129007135358990
來源:掘金

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市皿哨,隨后出現(xiàn)的幾起案子浅侨,更是在濱河造成了極大的恐慌,老刑警劉巖证膨,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仗颈,死亡現(xiàn)場離奇詭異,居然都是意外死亡椎例,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門请祖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來订歪,“玉大人,你說我怎么就攤上這事肆捕∷⒔” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眼虱。 經(jīng)常有香客問我喻奥,道長,這世上最難降的妖魔是什么捏悬? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任撞蚕,我火速辦了婚禮,結(jié)果婚禮上过牙,老公的妹妹穿的比我還像新娘甥厦。我一直安慰自己,他們只是感情好寇钉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布刀疙。 她就那樣靜靜地躺著,像睡著了一般扫倡。 火紅的嫁衣襯著肌膚如雪谦秧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天撵溃,我揣著相機(jī)與錄音疚鲤,去河邊找鬼。 笑死征懈,一個(gè)胖子當(dāng)著我的面吹牛石咬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卖哎,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼鬼悠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了亏娜?” 一聲冷哼從身側(cè)響起焕窝,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎维贺,沒想到半個(gè)月后它掂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溯泣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年虐秋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垃沦。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡客给,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肢簿,到底是詐尸還是另有隱情靶剑,我是刑警寧澤蜻拨,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站桩引,受9級特大地震影響缎讼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坑匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一血崭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笛辟,春花似錦功氨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至围来,卻和暖如春跺涤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背监透。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工桶错, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胀蛮。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓院刁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親粪狼。 傳聞我的和親對象是個(gè)殘疾皇子退腥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344