SpringBoot整合Jackson超詳細(xì)用法(附Jackson工具類)
一、Jackson簡(jiǎn)介
說(shuō)明:本篇講的是Jackson的詳細(xì)用法,Jackson工具類在文章最后,直接復(fù)制粘貼即可使用。 Jackson是公司中必用的組件之一,常用的還用阿里的Fastjson,但是由于一些原因bug與漏洞是在是太多,在注重安全的公司直接被pass,還有就是谷歌的Gson(這個(gè)沒(méi)用過(guò)不太了解)。 Spring MVC 的默認(rèn) json 解析器便是 Jackson。 Jackson 優(yōu)點(diǎn)很多。 Jackson 所依賴的 jar 包較少 ,簡(jiǎn)單易用。與其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比較快;Jackson 運(yùn)行時(shí)占用內(nèi)存比較低,性能比較好;Jackson 有靈活的 API,可以很容易進(jìn)行擴(kuò)展和定制。
額外了解:
Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,
當(dāng)升級(jí)到 2.x 版本時(shí),包名變?yōu)?code>com.fasterxml.jackson。
Jackson 有三個(gè)核心包,分別是 Streaming、Databid、Annotations,通過(guò)這些包可以方便的對(duì) JSON 進(jìn)行操作.
jackson-core:核心包,提供基于"流模式"解析的相關(guān) API,它包括 JsonPaser 和 JsonGenerator。 Jackson 內(nèi)部實(shí)現(xiàn)正是通過(guò)高性能的流模式 API 的 JsonGenerator 和 JsonParser 來(lái)生成和解析 json。jackson-annotations:注解包,提供標(biāo)準(zhǔn)注解功能.jackson-databind:數(shù)據(jù)綁定包, 提供基于"對(duì)象綁定" 解析的相關(guān) API ( ObjectMapper ) 和"樹(shù)模型" 解析的相關(guān) API (JsonNode);基于"對(duì)象綁定" 解析的 API 和"樹(shù)模型"解析的 API 依賴基于"流模式"解析的 API。包含上面兩個(gè)包,只導(dǎo)入這個(gè)坐標(biāo)即可。
運(yùn)行環(huán)境:
idea2020.2jdk1.8springboot 2.7.9
下載demo:直接去我的資源下載即可(Jackson實(shí)例-附工具類)
二、Json簡(jiǎn)介
說(shuō)明: 作為Java開(kāi)發(fā)一定要學(xué)習(xí)Json,在現(xiàn)在的前后端分離的項(xiàng)目中,Json是最常見(jiàn)的數(shù)據(jù)交換格式。比如SpringBoot中@RequestBody注解就是作為接收J(rèn)son格式的注解,在使用Postman進(jìn)行測(cè)試時(shí)傳輸?shù)膔aw-json也是Json格式數(shù)據(jù)。
JSON表示結(jié)構(gòu):
對(duì)象數(shù)組: 對(duì)象結(jié)構(gòu)以”{”大括號(hào)開(kāi)始,以”}”大括號(hào)結(jié)束,中間部分由0或多個(gè)以”,”分隔的”key(關(guān)鍵字)/value(值)”對(duì)構(gòu)成,關(guān)鍵字和值之間以”:”分隔,語(yǔ)法結(jié)構(gòu)如代碼。這里給一個(gè)示例。
{
"array": [1,2,3],
"boolean": true,
"name": "cllb",
"null": null,
"age": 12345,
"object": {
"height": 100,
"color": "紅色"
},
"string": "陳老老老板"
}三、springboot整合Jackson
1.創(chuàng)建項(xiàng)目
說(shuō)明: 創(chuàng)建一個(gè)空springboot項(xiàng)目(2.7.9版本)。這里就不過(guò)多復(fù)述了,創(chuàng)建時(shí)將lombok組件選上,十分方便無(wú)需再寫(xiě)Get/Set方法。
注意:可以看到導(dǎo)入databind包會(huì)自動(dòng)導(dǎo)入剩下兩個(gè)包。

2.導(dǎo)入坐標(biāo)
說(shuō)明: 可以看到導(dǎo)入databind包會(huì)自動(dòng)導(dǎo)入剩下兩個(gè)包。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
3.配置文件
a.配置文件配置
properties格式:
#指定日期格式,比如yyyy-MM-dd HH:mm:ss,或者具體的格式化類的全限定名 spring.jackson.date-format #指定日期格式化時(shí)區(qū),比如America/Los_Angeles或者GMT+10. spring.jackson.time-zone #是否開(kāi)啟Jackson的反序列化 spring.jackson.deserialization #是否開(kāi)啟json的generators. spring.jackson.generator #指定Joda date/time的格式,比如yyyy-MM-ddHH:mm:ss). 如果沒(méi)有配置的話,dateformat會(huì)作為backup spring.jackson.joda-date-time-format #指定json使用的Locale. spring.jackson.locale #是否開(kāi)啟Jackson通用的特性. spring.jackson.mapper #是否開(kāi)啟jackson的parser特性. spring.jackson.parser #指定PropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)或者指定PropertyNamingStrategy子類的全限定類名. spring.jackson.property-naming-strategy #是否開(kāi)啟jackson的序列化. spring.jackson.serialization #指定序列化時(shí)屬性的inclusion方式,具體查看JsonInclude.Include枚舉. spring.jackson.serialization-inclusion
yml格式:
spring:
jackson:
#日期格式化
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
#設(shè)置空如何序列化
default-property-inclusion: non_null
serialization:
#格式化輸出
indent_output: true
#忽略無(wú)法轉(zhuǎn)換的對(duì)象
fail_on_empty_beans: false
deserialization:
#允許對(duì)象忽略json中不存在的屬性
fail_on_unknown_properties: false
parser:
#允許出現(xiàn)特殊字符和轉(zhuǎn)義符
allow_unquoted_control_chars: true
#允許出現(xiàn)單引號(hào)
allow_single_quotes: trueb.自定義配置
說(shuō)明: 這里直接將Jackson工具類給大家,自定義配置指的就是工具類中,對(duì)于object_mapper的set賦值。什么方法都有,演示也直接使用工具類進(jìn)行。
package com.clllb.jackson.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
@Slf4j
public class JacksonUtil {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final ObjectMapper OBJECT_MAPPER_SNAKE_CASE = new ObjectMapper();
// 日期格式化
private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
//對(duì)象的所有字段全部列入
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//取消默認(rèn)轉(zhuǎn)換timestamps形式
OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//忽略空Bean轉(zhuǎn)json的錯(cuò)誤
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//所有的日期格式都統(tǒng)一為以下的樣式,即yyyy-MM-dd HH:mm:ss
OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
//忽略 在json字符串中存在,但是在java對(duì)象中不存在對(duì)應(yīng)屬性的情況。防止錯(cuò)誤
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
static {
//對(duì)象的所有字段全部列入
OBJECT_MAPPER_SNAKE_CASE.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//取消默認(rèn)轉(zhuǎn)換timestamps形式
OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//忽略空Bean轉(zhuǎn)json的錯(cuò)誤
OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//所有的日期格式都統(tǒng)一為以下的樣式,即yyyy-MM-dd HH:mm:ss
OBJECT_MAPPER_SNAKE_CASE.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
//忽略 在json字符串中存在,但是在java對(duì)象中不存在對(duì)應(yīng)屬性的情況。防止錯(cuò)誤
OBJECT_MAPPER_SNAKE_CASE.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//轉(zhuǎn)換為下劃線
OBJECT_MAPPER_SNAKE_CASE.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
}
private JacksonUtil() {
}
/**
* 對(duì)象轉(zhuǎn)Json格式字符串
*
* @param obj 對(duì)象
* @return Json格式字符串
*/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 對(duì)象轉(zhuǎn)file
* @param fileName
* @param obj
*/
public static void obj2File(String fileName,Object obj){
if (obj == null){
return;
}
try {
OBJECT_MAPPER.writeValue(new File(fileName),obj);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 對(duì)象轉(zhuǎn)Json格式字符串; 屬性名從駝峰改為下劃線形式
*
* @param obj 對(duì)象
* @return Json格式字符串
*/
public static <T> String obj2StringFieldSnakeCase(T obj) {
if (obj == null) {
return null;
}
try {
ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 字符串轉(zhuǎn)換為自定義對(duì)象; 屬性名從下劃線形式改為駝峰
*
* @param str 要轉(zhuǎn)換的字符串
* @param clazz 自定義對(duì)象的class對(duì)象
* @return 自定義對(duì)象
*/
public static <T> T string2ObjFieldLowerCamelCase(String str, Class<T> clazz) {
if (StringUtils.isEmpty(str) || clazz == null) {
return null;
}
try {
ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* 字符串轉(zhuǎn)換為自定義對(duì)象(List); 屬性名從下劃線形式改為駝峰
*
* @param str 要轉(zhuǎn)換的字符串
* @param typeReference 自定義對(duì)象的typeReference List 對(duì)象
* @return 自定義對(duì)象
*/
public static <T> List<T> string2ListFieldLowerCamelCase(String str, TypeReference<List<T>> typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
return objectMapper.readValue(str, typeReference);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* 對(duì)象轉(zhuǎn)Json格式字符串(格式化的Json字符串)
*
* @param obj 對(duì)象
* @return 美化的Json格式字符串
*/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 字符串轉(zhuǎn)換為自定義對(duì)象
*
* @param str 要轉(zhuǎn)換的字符串
* @param clazz 自定義對(duì)象的class對(duì)象
* @return 自定義對(duì)象
*/
public static <T> T string2Obj(String str, Class<T> clazz) {
if (StringUtils.isEmpty(str) || clazz == null) {
return null;
}
try {
return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* 字符串轉(zhuǎn)換為自定義字段轉(zhuǎn)為list
* @param str
* @param typeReference
* @param <T>
* @return
*/
public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
return (T) (typeReference.getType().equals(String.class) ? str : OBJECT_MAPPER.readValue(str, typeReference));
} catch (IOException e) {
log.warn("Parse String to Object error", e);
return null;
}
}
public static <T> T string2Obj(String str, Class<?> collectionClazz, Class<?>... elementClazzes) {
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClazz, elementClazzes);
try {
return OBJECT_MAPPER.readValue(str, javaType);
} catch (IOException e) {
log.warn("Parse String to Object error : {}" + e.getMessage());
return null;
}
}
}
4.實(shí)體類
說(shuō)明: 這里創(chuàng)建一個(gè)user實(shí)體類
package com.clllb.jackson.PO;
import lombok.Data;
import java.util.List;
@Data
public class User {
private String username;
private Integer age;
private List<String> info;
private Long userId;
}項(xiàng)目樣圖:

5.測(cè)試類
說(shuō)明: 測(cè)試類中直接調(diào)工具類中的方法,非常簡(jiǎn)單,附輸出結(jié)果。
a.object類型轉(zhuǎn)Json
說(shuō)明: 使用writeValueAsString方法
@Test
void obj2string(){
User user = new User();
user.setUsername("clllb");
user.setAge(24);
user.setUserId(1L);
List<String> infoList = new ArrayList<>();
infoList.add("有一百萬(wàn)");
infoList.add("發(fā)大財(cái)");
user.setInfo(infoList);
String json = JacksonUtil.obj2String(user);
System.out.println(json);
}
輸出結(jié)果:
{"username":"clllb","age":24,"info":["有一百萬(wàn)","發(fā)大財(cái)"],"userId":1}
b.object類型轉(zhuǎn)file
說(shuō)明: 使用writeValue方法
@Test
void obj2file(){
User user = new User();
user.setUsername("clllb");
user.setAge(24);
user.setUserId(1L);
List<String> infoList = new ArrayList<>();
infoList.add("有一百萬(wàn)");
infoList.add("發(fā)大財(cái)");
user.setInfo(infoList);
String fileName = "ccccc";
JacksonUtil.obj2File(fileName,user);
}
輸出結(jié)果:

c.string類型轉(zhuǎn)Object自定義類型
說(shuō)明: 使用readValue方法
@Test
void string2obj(){
String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百萬(wàn)\",\"發(fā)大財(cái)\"],\"userId\":11}";
User user = JacksonUtil.string2Obj(json, User.class);
System.out.println(user);
}
輸出結(jié)果:
User(username=clllb, age=24, info=[有一百萬(wàn), 發(fā)大財(cái)], userId=11)
d.string類型轉(zhuǎn)Object自定義類型list
說(shuō)明: 使用readValue方法,傳參變?yōu)門(mén)ypeReference typeReference,這里工具類用的重載方法名是相同的。
@Test
void string2objList(){
String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百萬(wàn)\",\"發(fā)大財(cái)\"],\"userId\":11},\n" +
"{\"username\":\"陳老老老板\",\"age\":25,\"info\":[\"有一千萬(wàn)\",\"發(fā)大大財(cái)\"],\"userId\":12}]";
List<User> user = JacksonUtil.string2Obj(json, new TypeReference<List<User>>(){});
user.forEach(System.out::println);
}
輸出結(jié)果:
User(username=clllb, age=24, info=[有一百萬(wàn), 發(fā)大財(cái)], userId=11)
User(username=陳老老老板, age=25, info=[有一千萬(wàn), 發(fā)大大財(cái)], userId=12)
e.object類型轉(zhuǎn)String(駝峰轉(zhuǎn)下劃線)
說(shuō)明: 使用writeValueAsString方法,這里區(qū)別看工具類就會(huì)發(fā)現(xiàn),就是多了一個(gè)設(shè)置OBJECT_MAPPER_SNAKE_CASE.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
@Test
void obj2sringSnakeCase(){
User user = new User();
user.setUsername("clllb");
user.setAge(24);
user.setUserId(11L);
List<String> infoList = new ArrayList<>();
infoList.add("有一百萬(wàn)");
infoList.add("發(fā)大財(cái)");
user.setInfo(infoList);
String json = JacksonUtil.obj2StringFieldSnakeCase(user);
System.out.println(json);
}輸出結(jié)果:
{"username":"clllb","age":24,"info":["有一百萬(wàn)","發(fā)大財(cái)"],"user_id":11}
f.string類型(下劃線)轉(zhuǎn)Object類型
<font color = 'red'><b>說(shuō)明:</font> 使用readValue方法
```java
@Test
void string2obj(){
String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百萬(wàn)\",\"發(fā)大財(cái)\"],\"user_id\":11}";
User user = JacksonUtil.string2Obj(json, User.class);
System.out.println(user);
}
輸出結(jié)果:
User(username=clllb, age=24, info=[有一百萬(wàn), 發(fā)大財(cái)], userId=11)
g.string類型(下劃線)轉(zhuǎn)Object自定義類型list
說(shuō)明: 使用readValue方法,傳參變?yōu)門(mén)ypeReference typeReference,這里工具類用的重載方法名是相同的。
@Test
void string2objSnakeCase(){
String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百萬(wàn)\",\"發(fā)大財(cái)\"],\"user_id\":11},\n" +
"{\"username\":\"陳老老老板\",\"age\":25,\"info\":[\"有一千萬(wàn)\",\"發(fā)大大財(cái)\"],\"user_id\":12}]";
List<User> user = JacksonUtil.string2ListFieldLowerCamelCase(json, new TypeReference<List<User>>(){});
user.forEach(System.out::println);
}
輸出結(jié)果:
User(username=clllb, age=24, info=[有一百萬(wàn), 發(fā)大財(cái)], userId=11)
User(username=陳老老老板, age=25, info=[有一千萬(wàn), 發(fā)大大財(cái)], userId=12)
總結(jié):工具類非常好用,包含日常所需。Jackson常見(jiàn)用法總結(jié)。希望對(duì)您有幫助,感謝閱讀
到此這篇關(guān)于SpringBoot整合Jackson超詳細(xì)教程的文章就介紹到這了,更多相關(guān)SpringBoot整合Jackson內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+springboot前后端分離工程跨域問(wèn)題解決方案解析
這篇文章主要介紹了vue+springboot前后端分離工程跨域問(wèn)題解決方案解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Struts2源碼分析之ParametersInterceptor攔截器
這篇文章主要介紹了Struts2源碼分析之ParametersInterceptor攔截器,ParametersInterceptor攔截器其主要功能是把ActionContext中的請(qǐng)求參數(shù)設(shè)置到ValueStack中,,需要的朋友可以參考下2019-06-06
logback的DuplicateMessageFilter日志過(guò)濾操作源碼解讀
這篇文章主要為大家介紹了logback的DuplicateMessageFilter日志過(guò)濾操作源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
Java實(shí)現(xiàn)重定向過(guò)程中添加請(qǐng)求頭信息
在Java中,我們經(jīng)常需要使用網(wǎng)絡(luò)請(qǐng)求來(lái)與服務(wù)器進(jìn)行通信,在進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí),有時(shí)我們需要在重定向過(guò)程中添加請(qǐng)求頭信息,本文將介紹如何使用Java在重定向過(guò)程中添加請(qǐng)求頭,并提供相應(yīng)的代碼示例,2023-10-10
Java中的LinkedHashMap及LRU緩存機(jī)制詳解
這篇文章主要介紹了Java中的LinkedHashMap及LRU緩存機(jī)制詳解,LinkedHashMap繼承自HashMap,它的多種操作都是建立在HashMap操作的基礎(chǔ)上的,同HashMap不同的是,LinkedHashMap維護(hù)了一個(gè)Entry的雙向鏈表,保證了插入的Entry中的順序,需要的朋友可以參考下2023-09-09
java實(shí)現(xiàn)網(wǎng)頁(yè)驗(yàn)證碼功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)網(wǎng)頁(yè)驗(yàn)證碼功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10

