目录
- 一、Jackson简介
- 二、Json简介
- 三、springboot整合Jackson
- 1.创建项目
- 2.导入坐标
- 3.配置文件
- 4.实体类
- 5.测试类
一、Jackson简介
说明:本篇讲的是Jackson的详细用法,Jackson工具类在文章最后,直接复制粘贴即可使用。 Jackson是公司中必用的组件之一,常用的还用阿里的Fastjson,但是由于一些原因bug与漏洞是在是太多,在注重安全的公司直接被pass,还有就是谷歌的Gson(这个没用过不太了解)。 Spring MVC 的默认 json 解析器便是 Jackson。 Jackson 优点很多。 Jackson 所依赖的 jar 包较少 ,简单易用。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。
额外了解:
Jackson 的 1.x 版本的包名是 org.codehaus.jackson
,
当升级到 2.x 版本时,包名变为com.fasterxml.jackson
。
Jackson 有三个核心包,分别是 Streaming
、Databid
、Annotations
,通过这些包可以方便的对 JSON 进行操作.
jackson-core
:核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。jackson-annotations
:注解包,提供标准注解功能.jackson-databind
:数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。包含上面两个包,只导入这个坐标即可。
运行环境:
idea2020.2
jdk1.8
springboot 2.7.9
下载demo:直接去我的资源下载即可(Jackson实例-附工具类)
二、Json简介
说明: 作为Java开发一定要学习Json,在现在的前后端分离的项目中,Json是最常见的数据交换格式。比如SpringBoot中@RequestBody注解就是作为接收Json格式的注解,在使用Postman进行测试时传输的raw-json也是Json格式数据。
JSON表示结构:
对象数组: 对象结构以”{”大括号开始,以”}”大括号结束,中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如代码。这里给一个示例。
{ | |
"array": [1,2,3], | |
"boolean": true, | |
"name": "cllb", | |
"null": null, | |
"age": 12345, | |
"object": { | |
"height": 100, | |
"color": "红色" | |
}, | |
"string": "陈老老老板" | |
} |
三、springboot整合Jackson
1.创建项目
说明: 创建一个空springboot项目(2.7.9版本)。这里就不过多复述了,创建时将lombok组件选上,十分方便无需再写Get/Set方法。
注意:可以看到导入databind包会自动导入剩下两个包。
2.导入坐标
说明: 可以看到导入databind包会自动导入剩下两个包。
<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 | |
#指定日期格式化时区,比如America/Los_Angeles或者GMT+10. | |
spring.jackson.time-zone | |
#是否开启Jackson的反序列化 | |
spring.jackson.deserialization | |
#是否开启json的generators. | |
spring.jackson.generator | |
#指定Joda date/time的格式,比如yyyy-MM-ddHH:mm:ss). 如果没有配置的话,dateformat会作为backup | |
spring.jackson.joda-date-time-format | |
#指定json使用的Locale. | |
spring.jackson.locale | |
#是否开启Jackson通用的特性. | |
spring.jackson.mapper | |
#是否开启jackson的parser特性. | |
spring.jackson.parser | |
#指定PropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)或者指定PropertyNamingStrategy子类的全限定类名. | |
spring.jackson.property-naming-strategy | |
#是否开启jackson的序列化. | |
spring.jackson.serialization | |
#指定序列化时属性的inclusion方式,具体查看JsonInclude.Include枚举. | |
spring.jackson.serialization-inclusion |
yml格式:
spring: | |
jackson: | |
#日期格式化 | |
date-format: yyyy-MM-dd HH:mm:ss | |
time-zone: GMT+8 | |
#设置空如何序列化 | |
default-property-inclusion: non_null | |
serialization: | |
#格式化输出 | |
indent_output: true | |
#忽略无法转换的对象 | |
fail_on_empty_beans: false | |
deserialization: | |
#允许对象忽略json中不存在的属性 | |
fail_on_unknown_properties: false | |
parser: | |
#允许出现特殊字符和转义符 | |
allow_unquoted_control_chars: true | |
#允许出现单引号 | |
allow_single_quotes: true |
b.自定义配置
说明: 这里直接将Jackson工具类给大家,自定义配置指的就是工具类中,对于object_mapper的set赋值。什么方法都有,演示也直接使用工具类进行。
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; | |
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 { | |
//对象的所有字段全部列入 | |
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS); | |
//取消默认转换timestamps形式 | |
OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); | |
//忽略空Bean转json的错误 | |
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); | |
//所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss | |
OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT)); | |
//忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误 | |
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | |
} | |
static { | |
//对象的所有字段全部列入 | |
OBJECT_MAPPER_SNAKE_CASE.setSerializationInclusion(JsonInclude.Include.ALWAYS); | |
//取消默认转换timestamps形式 | |
OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); | |
//忽略空Bean转json的错误 | |
OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); | |
//所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss | |
OBJECT_MAPPER_SNAKE_CASE.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT)); | |
//忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误 | |
OBJECT_MAPPER_SNAKE_CASE.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | |
//转换为下划线 | |
OBJECT_MAPPER_SNAKE_CASE.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); | |
} | |
private JacksonUtil() { | |
} | |
/** | |
* 对象转Json格式字符串 | |
* | |
* @param obj 对象 | |
* @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; | |
} | |
} | |
/** | |
* 对象转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(); | |
} | |
} | |
/** | |
* 对象转Json格式字符串; 属性名从驼峰改为下划线形式 | |
* | |
* @param obj 对象 | |
* @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; | |
} | |
} | |
/** | |
* 字符串转换为自定义对象; 属性名从下划线形式改为驼峰 | |
* | |
* @param str 要转换的字符串 | |
* @param clazz 自定义对象的class对象 | |
* @return 自定义对象 | |
*/ | |
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; | |
} | |
} | |
/** | |
* 字符串转换为自定义对象(List); 属性名从下划线形式改为驼峰 | |
* | |
* @param str 要转换的字符串 | |
* @param typeReference 自定义对象的typeReference List 对象 | |
* @return 自定义对象 | |
*/ | |
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; | |
} | |
} | |
/** | |
* 对象转Json格式字符串(格式化的Json字符串) | |
* | |
* @param obj 对象 | |
* @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; | |
} | |
} | |
/** | |
* 字符串转换为自定义对象 | |
* | |
* @param str 要转换的字符串 | |
* @param clazz 自定义对象的class对象 | |
* @return 自定义对象 | |
*/ | |
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; | |
} | |
} | |
/** | |
* 字符串转换为自定义字段转为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.实体类
说明: 这里创建一个user实体类
package com.clllb.jackson.PO; | |
import lombok.Data; | |
import java.util.List; | |
public class User { | |
private String username; | |
private Integer age; | |
private List<String> info; | |
private Long userId; | |
} |
项目样图:
5.测试类
说明: 测试类中直接调工具类中的方法,非常简单,附输出结果。
a.object类型转Json
说明: 使用writeValueAsString方法
@Test | |
void obj2string(){ | |
User user = new User(); | |
user.setUsername("clllb"); | |
user.setAge(24); | |
user.setUserId(1L); | |
List<String> infoList = new ArrayList<>(); | |
infoList.add("有一百万"); | |
infoList.add("发大财"); | |
user.setInfo(infoList); | |
String json = JacksonUtil.obj2String(user); | |
System.out.println(json); | |
} | |
输出结果:
{"username":"clllb","age":24,"info":["有一百万","发大财"],"userId":1}
b.object类型转file
说明: 使用writeValue方法
void obj2file(){ | |
User user = new User(); | |
user.setUsername("clllb"); | |
user.setAge(24); | |
user.setUserId(1L); | |
List<String> infoList = new ArrayList<>(); | |
infoList.add("有一百万"); | |
infoList.add("发大财"); | |
user.setInfo(infoList); | |
String fileName = "ccccc"; | |
JacksonUtil.obj2File(fileName,user); | |
} | |
输出结果:
c.string类型转Object自定义类型
说明: 使用readValue方法
void string2obj(){ | |
String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"userId\":11}"; | |
User user = JacksonUtil.string2Obj(json, User.class); | |
System.out.println(user); | |
} | |
输出结果:
User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
d.string类型转Object自定义类型list
说明: 使用readValue方法,传参变为TypeReference typeReference,这里工具类用的重载方法名是相同的。
void string2objList(){ | |
String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"userId\":11},\n" + | |
"{\"username\":\"陈老老老板\",\"age\":25,\"info\":[\"有一千万\",\"发大大财\"],\"userId\":12}]"; | |
List<User> user = JacksonUtil.string2Obj(json, new TypeReference<List<User>>(){}); | |
user.forEach(System.out::println); | |
} | |
输出结果:
User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
User(username=陈老老老板, age=25, info=[有一千万, 发大大财], userId=12)
e.object类型转String(驼峰转下划线)
说明: 使用writeValueAsString方法,这里区别看工具类就会发现,就是多了一个设置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("有一百万"); | |
infoList.add("发大财"); | |
user.setInfo(infoList); | |
String json = JacksonUtil.obj2StringFieldSnakeCase(user); | |
System.out.println(json); | |
} |
输出结果:
{"username":"clllb","age":24,"info":["有一百万","发大财"],"user_id":11}
f.string类型(下划线)转Object类型
<font color = 'red'><b>说明:</font> 使用readValue方法 | |
```java | |
void string2obj(){ | |
String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"user_id\":11}"; | |
User user = JacksonUtil.string2Obj(json, User.class); | |
System.out.println(user); | |
} | |
输出结果:
User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
g.string类型(下划线)转Object自定义类型list
说明: 使用readValue方法,传参变为TypeReference typeReference,这里工具类用的重载方法名是相同的。
void string2objSnakeCase(){ | |
String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"user_id\":11},\n" + | |
"{\"username\":\"陈老老老板\",\"age\":25,\"info\":[\"有一千万\",\"发大大财\"],\"user_id\":12}]"; | |
List<User> user = JacksonUtil.string2ListFieldLowerCamelCase(json, new TypeReference<List<User>>(){}); | |
user.forEach(System.out::println); | |
} | |
输出结果:
User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
User(username=陈老老老板, age=25, info=[有一千万, 发大大财], userId=12)
总结:工具类非常好用,包含日常所需。Jackson常见用法总结。希望对您有帮助,感谢阅读