在Java中使用Moshi?JSON庫(kù)的方法詳解
Moshi 是一個(gè)可用于 Java 與 Kotlin 的 JSON 序列化與反序列化庫(kù),其主要使用 Kotlin 編寫。本文以樣例代碼的方式來(lái)演示該庫(kù)在 Java 中的使用。
示例項(xiàng)目使用 Maven 管理,下面列出寫作本文時(shí)用到的 JDK、Maven 及 Moshi 的版本:
JDK:Amazon Corretto 17.0.8 Maven:3.9.2 Moshi:1.18.30
開始前,需要在pom.xml
的<dependencies>
下引入 Moshi 依賴(moshi
為核心模塊,moshi-adapters
模塊包含諸如Date
類型處理等實(shí)用的 Adapter):
<!-- pom.xml --> <dependency> <groupId>com.squareup.moshi</groupId> <artifactId>moshi</artifactId> <version>1.18.30</version> </dependency> <dependency> <groupId>com.squareup.moshi</groupId> <artifactId>moshi-adapters</artifactId> <version>1.18.30</version> </dependency>
為了省去編寫繁瑣的Setters
與Getters
,該示例項(xiàng)目還使用了 Lombok,依賴如下:
<!-- pom.xml --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
此外,我們以編寫 JUnit 單元測(cè)試的方式來(lái)演示 Moshi 的使用,所以還需引入junit-jupiter
依賴:
<!-- pom.xml --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency>
準(zhǔn)備好后,即可以開始使用了。
1 基礎(chǔ)使用
首先,看一下最基礎(chǔ)的使用,即如何使用 Moshi 進(jìn)行序列化與反序列化(即 Java 對(duì)象轉(zhuǎn)換為 JSON,以及 JSON 轉(zhuǎn)換為 Java 對(duì)象)。
先新建一個(gè) Model 類,本文以User
為例,該類有三個(gè)字段:name
、roles
和createdAt
,包括了String
、List
、Date
以及枚舉類型。
// src/main/java/com/example/demo/model/User.java package com.example.demo.model; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import java.util.Date; import java.util.List; @ToString @Getter @Setter @NoArgsConstructor public class User { private String name; private List<Role> roles; private Date createdAt; public enum Role { ADMIN, EDITOR, VIEWER } }
下面即編寫一個(gè)測(cè)試用例來(lái)演示 User 對(duì)象與 JSON 的互轉(zhuǎn):
// src/test/java/com/example/demo/MoshiTest#testBasicUsage @Test public void testBasicUsage() { // 構(gòu)造 Moshi 實(shí)例 Moshi moshi = new Moshi.Builder() .add(Date.class, new Rfc3339DateJsonAdapter()) .build(); // 獲取 User 的 JsonAdapter JsonAdapter<User> jsonAdapter = moshi.adapter(User.class); // 構(gòu)造 User 對(duì)象 User user = new User(); user.setName("Larry"); user.setRoles(List.of(User.Role.ADMIN, User.Role.EDITOR)); user.setCreatedAt(new Date()); // 序列化 String json = jsonAdapter.toJson(user); System.out.println(json); // 反序列化 try { User userParsed = jsonAdapter.fromJson(json); System.out.println(userParsed); } catch (IOException e) { e.printStackTrace(); } }
需要注意的是,如上代碼在構(gòu)造 Moshi 實(shí)例時(shí)指定了Date
類型對(duì)應(yīng)的 JSON Adapter Rfc3339DateJsonAdapter
,否則在解析該類型字段時(shí)會(huì)報(bào)錯(cuò)。
如上代碼運(yùn)行結(jié)果如下:
{"createdAt":"2023-10-14T09:47:37.763Z","name":"Larry","roles":["ADMIN","EDITOR"]}
User(name=Larry, roles=[ADMIN, EDITOR], createdAt=Sat Oct 14 17:47:37 CST 2023)
可以看到,User 對(duì)象序列化為的 JSON、JSON 反序列化為的 User 對(duì)象都是正確的。
2 使用 @Json 自定義字段名
上面的例子中,JSON 里的字段名與 Java 類里的屬性名是完全一致的。
如果某個(gè)字段名需要自定義,該怎么做呢?下面即進(jìn)行了演示:
// src/main/java/com/example/demo/model/User.java package com.example.demo.model; @ToString @Getter @Setter @NoArgsConstructor public class User { // ... @Json(name = "created_at") private Date createdAt; // ... }
可以看到,只需在 Java 類對(duì)應(yīng)的屬性上加上@Json
注解,然后自定義其名稱就可以了。
再次運(yùn)行一下上面的測(cè)試用例(src/test/java/com/example/demo/MoshiTest#testBasicUsage
),得到了如下結(jié)果:
{"created_at":"2023-10-14T09:55:48.793Z","name":"Larry","roles":["ADMIN","EDITOR"]}
User(name=Larry, roles=[ADMIN, EDITOR], createdAt=Sat Oct 14 17:55:48 CST 2023)
可以看到,User 類的createdAt
屬性在序列化為 JSON 時(shí)變?yōu)榱?code>created_at;該 JSON 再次反序列化為 User 對(duì)象時(shí),createdAt
屬性的賦值也是正常的。
3 自定義 Adapter
前面的例子中,我們?yōu)?code>Date類型指定了 Moshi 自帶的 Adapter Rfc3339DateJsonAdapter
來(lái)支持其解析。如果覺得這個(gè) Adapter 解析后的日期格式不是想要的,有辦法自己指定嗎?當(dāng)然是可以的,Moshi 支持我們針對(duì)某種類型使用自定義 Adapter 來(lái)實(shí)現(xiàn)其序列化與反序列化邏輯。
下面即對(duì) User 類中的枚舉類型Role
編寫一個(gè)自定義 Adapter 來(lái)實(shí)現(xiàn)其自定義解析:
// src/main/java/com/example/demo/adapter/RoleAdapter.java package com.example.demo.adapter; import com.example.demo.model.User; import com.squareup.moshi.FromJson; import com.squareup.moshi.ToJson; public class RoleAdapter { @ToJson public String toJson(User.Role role) { return role.name().substring(0, 1); } @FromJson public User.Role fromJson(String role) { switch (role.charAt(0)) { case 'A': return User.Role.ADMIN; case 'E': return User.Role.EDITOR; case 'V': return User.Role.VIEWER; } return null; } }
可以看到,我們?yōu)?code>Role類型編寫一個(gè)自定義 Adapter RoleAdapter
。該類中有兩個(gè)方法toJson
與fromJson
,且分別被加上了注解@ToJson
與@FromJson
,這兩個(gè)方法分別用于Role
類型由 Java 屬性轉(zhuǎn)為 JSON 字段以及由 JSON 字段轉(zhuǎn)換為 Java 屬性時(shí)的邏輯(本示例僅取第一個(gè)字母來(lái)表示 User 擁有的Role
)。
下面編寫一個(gè)測(cè)試用例來(lái)演示該自定義 Adapter 的使用:
// src/test/java/com/example/demo/MoshiTest#testCustomTypeAdapter @Test public void testCustomTypeAdapter() { // 構(gòu)造 Moshi 實(shí)例 Moshi moshi = new Moshi.Builder() .add(Date.class, new Rfc3339DateJsonAdapter()) .add(new RoleAdapter()) .build(); // 獲取 User 的 JsonAdapter JsonAdapter<User> jsonAdapter = moshi.adapter(User.class); // 構(gòu)造 User 對(duì)象 User user = new User(); user.setName("Larry"); user.setRoles(List.of(User.Role.ADMIN, User.Role.EDITOR)); user.setCreatedAt(new Date()); // 序列化 String json = jsonAdapter.toJson(user); System.out.println(json); // 反序列化 try { User userParsed = jsonAdapter.fromJson(json); System.out.println(userParsed); } catch (IOException e) { e.printStackTrace(); } }
可以看到,只需在構(gòu)造 Moshi 實(shí)例時(shí),添加上該 Adapter 即可。
運(yùn)行一下該測(cè)試用例,得到的結(jié)果如下:
{"created_at":"2023-10-14T10:39:04.174Z","name":"Larry","roles":["A","E"]}
User(name=Larry, roles=[ADMIN, EDITOR], createdAt=Sat Oct 14 18:39:04 CST 2023)
可以看到,User 對(duì)象序列化為的 JSON 中,roles
字段的值使用了我們的自定義邏輯(僅取第一個(gè)字母來(lái)表示 User 的 Role);該 JSON 再次反序列化為的 User 對(duì)象也使用了我們的自定義邏輯,反序列化結(jié)果也是正確的。
4 JSON 數(shù)組如何處理?
上面演示的均為 Java 對(duì)象與 JSON 對(duì)象的互相轉(zhuǎn)換,Java List 如何與 JSON 數(shù)組互相轉(zhuǎn)換呢?
下面的測(cè)試用例作了演示:
// src/test/java/com/example/demo/MoshiTest#testJSONArrayParsing @Test public void testJSONArrayParsing() { // 新建一個(gè)類型 Type type = Types.newParameterizedType(List.class, User.class); // 構(gòu)造 Moshi 實(shí)例 Moshi moshi = new Moshi.Builder() .add(Date.class, new Rfc3339DateJsonAdapter()) .add(new RoleAdapter()) .build(); // 獲取 User 的 JsonAdapter JsonAdapter<List<User>> jsonAdapter = moshi.adapter(type); // 構(gòu)造 User 對(duì)象 User user = new User(); user.setName("Larry"); user.setCreatedAt(new Date()); user.setRoles(List.of(User.Role.ADMIN, User.Role.EDITOR)); // 序列化 String json = jsonAdapter.toJson(List.of(user)); System.out.println(json); // 反序列化 try { List<User> usersParsed = jsonAdapter.fromJson(json); System.out.println(usersParsed); } catch (IOException e) { e.printStackTrace(); } }
可以看到,只需新建一個(gè) Moshi Type 即可,使用起來(lái)也一樣簡(jiǎn)單。
如上測(cè)試用例的運(yùn)行結(jié)果如下:
[{"created_at":"2023-10-14T11:22:27.153Z","name":"Larry","roles":["A","E"]}]
[User(name=Larry, roles=[ADMIN, EDITOR], createdAt=Sat Oct 14 19:22:27 CST 2023)]
可以看到,User List 與 JSON Array 的互相轉(zhuǎn)換結(jié)果均是正確的。
綜上,本文探索了在 Java 中使用 Moshi 進(jìn)行 JSON 序列化和反序列化的各種常見用法。
到此這篇關(guān)于在Java中使用Moshi JSON庫(kù)方法詳解的文章就介紹到這了,更多相關(guān)Java中使用Moshi JSON庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了java如何實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11Spring容器注冊(cè)組件實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Spring容器注冊(cè)組件實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java編程實(shí)現(xiàn)向文本文件中讀取數(shù)據(jù)之Scanner用法示例
這篇文章主要介紹了Java編程實(shí)現(xiàn)向文本文件中讀取數(shù)據(jù)之Scanner用法,結(jié)合實(shí)例形式分析了java使用Scanner類讀取文本文件相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-03-03logback 實(shí)現(xiàn)給變量指定默認(rèn)值
這篇文章主要介紹了logback 實(shí)現(xiàn)給變量指定默認(rèn)值操作,具有很好的參考家價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08SpringMVC 跨重定向請(qǐng)求傳遞數(shù)據(jù)的方法實(shí)現(xiàn)
這篇文章主要介紹了SpringMVC 跨重定向請(qǐng)求傳遞數(shù)據(jù)的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06