在Java中使用Moshi?JSON庫(kù)的方法詳解
Moshi 是一個(gè)可用于 Java 與 Kotlin 的 JSON 序列化與反序列化庫(kù),其主要使用 Kotlin 編寫(xiě)。本文以樣例代碼的方式來(lái)演示該庫(kù)在 Java 中的使用。
示例項(xiàng)目使用 Maven 管理,下面列出寫(xiě)作本文時(shí)用到的 JDK、Maven 及 Moshi 的版本:
JDK:Amazon Corretto 17.0.8 Maven:3.9.2 Moshi:1.18.30
開(kāi)始前,需要在pom.xml的<dependencies>下引入 Moshi 依賴(lài)(moshi為核心模塊,moshi-adapters模塊包含諸如Date類(lèi)型處理等實(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>
為了省去編寫(xiě)繁瑣的Setters與Getters,該示例項(xiàng)目還使用了 Lombok,依賴(lài)如下:
<!-- pom.xml -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
此外,我們以編寫(xiě) JUnit 單元測(cè)試的方式來(lái)演示 Moshi 的使用,所以還需引入junit-jupiter依賴(lài):
<!-- pom.xml -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
準(zhǔn)備好后,即可以開(kāi)始使用了。
1 基礎(chǔ)使用
首先,看一下最基礎(chǔ)的使用,即如何使用 Moshi 進(jìn)行序列化與反序列化(即 Java 對(duì)象轉(zhuǎn)換為 JSON,以及 JSON 轉(zhuǎn)換為 Java 對(duì)象)。
先新建一個(gè) Model 類(lèi),本文以User為例,該類(lèi)有三個(gè)字段:name、roles和createdAt,包括了String、List、Date以及枚舉類(lèi)型。
// 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
}
}
下面即編寫(xiě)一個(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類(lèi)型對(duì)應(yīng)的 JSON Adapter Rfc3339DateJsonAdapter,否則在解析該類(lèi)型字段時(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 類(lèi)里的屬性名是完全一致的。
如果某個(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 類(lèi)對(duì)應(yīng)的屬性上加上@Json注解,然后自定義其名稱(chēng)就可以了。
再次運(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 類(lèi)的createdAt屬性在序列化為 JSON 時(shí)變?yōu)榱?code>created_at;該 JSON 再次反序列化為 User 對(duì)象時(shí),createdAt屬性的賦值也是正常的。
3 自定義 Adapter
前面的例子中,我們?yōu)?code>Date類(lèi)型指定了 Moshi 自帶的 Adapter Rfc3339DateJsonAdapter 來(lái)支持其解析。如果覺(jué)得這個(gè) Adapter 解析后的日期格式不是想要的,有辦法自己指定嗎?當(dāng)然是可以的,Moshi 支持我們針對(duì)某種類(lèi)型使用自定義 Adapter 來(lái)實(shí)現(xiàn)其序列化與反序列化邏輯。
下面即對(duì) User 類(lèi)中的枚舉類(lèi)型Role編寫(xiě)一個(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類(lèi)型編寫(xiě)一個(gè)自定義 Adapter RoleAdapter。該類(lèi)中有兩個(gè)方法toJson與fromJson,且分別被加上了注解@ToJson與@FromJson,這兩個(gè)方法分別用于Role類(lèi)型由 Java 屬性轉(zhuǎn)為 JSON 字段以及由 JSON 字段轉(zhuǎn)換為 Java 屬性時(shí)的邏輯(本示例僅取第一個(gè)字母來(lái)表示 User 擁有的Role)。
下面編寫(xiě)一個(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è)類(lèi)型
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 序列化和反序列化的各種常見(jiàn)用法。
到此這篇關(guān)于在Java中使用Moshi JSON庫(kù)方法詳解的文章就介紹到這了,更多相關(guān)Java中使用Moshi JSON庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java NIO.2 使用Path接口來(lái)監(jiān)聽(tīng)文件、文件夾變化
Java7對(duì)NIO進(jìn)行了大的改進(jìn),新增了許多功能,接下來(lái)通過(guò)本文給大家介紹Java NIO.2 使用Path接口來(lái)監(jiān)聽(tīng)文件、文件夾變化 ,需要的朋友可以參考下2019-05-05
詳解java中this.getClass()和super.getClass()的實(shí)例
這篇文章主要介紹了詳解java中this.getClass()和super.getClass()的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-08-08
Spring/SpringBoot?@RequestParam注解無(wú)法讀取application/json格式數(shù)據(jù)問(wèn)題
RequestParam用于將指定的請(qǐng)求參數(shù)賦值給方法中的形參,可以接受簡(jiǎn)單類(lèi)型屬性,也可以接受對(duì)象類(lèi)型,一般用于GET請(qǐng)求,下面這篇文章主要給大家介紹了關(guān)于Spring/SpringBoot?@RequestParam注解無(wú)法讀取application/json格式數(shù)據(jù)問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2022-10-10
使用springcloud+oauth2攜帶token去請(qǐng)求其他服務(wù)
這篇文章主要介紹了使用springcloud+oauth2攜帶token去請(qǐng)求其他服務(wù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
java獲取登錄者IP和登錄時(shí)間的兩種實(shí)現(xiàn)代碼詳解
這篇文章主要介紹了java獲取登錄者IP和登錄時(shí)間的實(shí)現(xiàn)代碼,本文通過(guò)兩種結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
springboot整合日志處理Logback的實(shí)現(xiàn)示例
Logback是由log4j創(chuàng)始人設(shè)計(jì)的又一個(gè)開(kāi)源日志組件,本文主要介紹了springboot整合日志處理Logback,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
JPA如何將查詢(xún)結(jié)果轉(zhuǎn)換為DTO對(duì)象
這篇文章主要介紹了JPA如何將查詢(xún)結(jié)果轉(zhuǎn)換為DTO對(duì)象,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java服務(wù)端性能優(yōu)化之JVM垃圾回收策略詳解
JVM垃圾回收策略涵蓋了基本原理、常見(jiàn)策略(如SerialGC、ParallelGC、CMS、G1GC)以及優(yōu)化建議,選擇合適的策略和調(diào)整參數(shù),如堆大小和GC日志,可以提高應(yīng)用性能和響應(yīng)速度,持續(xù)監(jiān)控和分析是關(guān)鍵步驟2025-03-03
RabbitMQ消費(fèi)者限流實(shí)現(xiàn)消息處理優(yōu)化
這篇文章主要介紹了RabbitMQ消費(fèi)者限流實(shí)現(xiàn)消息處理優(yōu)化,消費(fèi)者限流是用于消費(fèi)者每次獲取消息時(shí)限制條數(shù),注意前提是手動(dòng)確認(rèn)模式,并且在手動(dòng)確認(rèn)后才能獲取到消息,感興趣想要詳細(xì)了解可以參考下文2023-05-05

