用好Jackson,操作Json节省一半时间
前言
目前解析Json的工具包有,Gson,FastJson,Jackson,Json-lib。综合来看,Jackson的性能较优,稳定性也比较高,而且spring-boot-starter-web默认会引入Jackson包。因此介绍一下Jackson的使用。
Jackson目前有2个版本 1.x版本包名为org.codehaus.jackson 2.x版本包名为com.fasterxml.jackson
使用
在pom中加入如下依赖即可。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.2</version>
</dependency>
前文说过,当使用spring-boot-starter-web模块时,会默认引入Jackson包,不必在pom中再次引入上面依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
序列化
将java对象序列化成json,@Data注解是用lombok插件来自动生成get和set方法
@Data
public class Student {
/** 名字 */
private String name;
/** 年龄 */
private Integer age;
/** 头像 */
private String profileImageUrl;
}
将常用的方法封装成一个常用的工具类,如下所示,有2个好处
- ObjectMapper 类只会生成一个,节省空间
- 可以定义统一的配置(后面细说)
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
/** 将对象转为string */
public static <T> String obj2String(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String)obj : objectMapper.writeValueAsString(obj);
} catch (Exception e) {
log.warn("Parse Object to String error",e);
return null;
}
}
}
先简单介绍一下封装的工具类
1. 将对象转为json
public static <T> String obj2String(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String)obj : objectMapper.writeValueAsString(obj);
} catch (Exception e) {
log.warn("Parse Object to String error",e);
return null;
}
}
各种类型均可
@Test
public void obj2String() throws Exception {
Student student = new Student();
student.setAge(10);
student.setName("name");
student.setProfileImageUrl("link");
String result = JsonUtil.obj2String(student);
// {"name":"name","age":10,"profileImageUrl":"link"}
System.out.println(result);
Map<String, List<Integer>> map = new HashMap<>();
map.put("a", Arrays.asList(1, 2, 3));
map.put("b", Arrays.asList(1, 2, 3));
String result1 = JsonUtil.obj2String(map);
// {"a":[1,2,3],"b":[1,2,3]}
System.out.println(result1);
}
2. 将对象转为json,并格式化的输出
public static <T> String obj2StringPretty(T obj){
if(obj == null){
return null;
}
try {
return obj instanceof String ? (String)obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (Exception e) {
log.warn("Parse Object to String error",e);
return null;
}
}
@Test
public void obj2StringPretty() throws Exception {
Student student = new Student();
student.setAge(10);
student.setName("name");
student.setProfileImageUrl("link");
String result = JsonUtil.obj2StringPretty(student);
/*
{
"name" : "name",
"age" : 10,
"profileImageUrl" : "link"
}
*/
System.out.println(result);
Map<String, List<Integer>> map = new HashMap<>();
map.put("a", Arrays.asList(1, 2, 3));
map.put("b", Arrays.asList(1, 2, 3));
String result1 = JsonUtil.obj2StringPretty(map);
/*
{
"a" : [ 1, 2, 3 ],
"b" : [ 1, 2, 3 ]
}
*/
System.out.println(result1);
}
反序列化
将json转为java对象
方式1
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 : objectMapper.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error",e);
return null;
}
}
基本类型的转换
@Test
public void string2Obj() throws Exception {
String str = "{"name":"name","age":10,"profileImageUrl":"link"}";
Student student = JsonUtil.string2Obj(str, Student.class);
// Student(name=name, age=10, profileImageUrl=link)
System.out.println(student);
}
各种复杂类型的转换,示例1
@Test
public void string2Obj1() throws Exception {
Student student1 = new Student();
student1.setAge(10);
student1.setName("name1");
student1.setProfileImageUrl("link1");
Student student2 = new Student();
student2.setAge(20);
student2.setName("name2");
student2.setProfileImageUrl("link2");
List<Student> studentList = new ArrayList<>();
studentList.add(student1);
studentList.add(student2);
String result = JsonUtil.obj2String(studentList);
// [{"name":"name1","age":10,"profileImageUrl":"link1"},{"name":"name2","age":20,"profileImageUrl":"link2"}]
System.out.println(result);
List<Student> finalList = JsonUtil.string2Obj(result, List.class);
// [{name=name1, age=10, profileImageUrl=link1}, {name=name2, age=20, profileImageUrl=link2}]
System.out.println(finalList);
}
复杂类型的转换,示例2
@Test
public void string2Obj2() throws Exception {
Map<String, List<Integer>> testMap = new HashMap<>();
testMap.put("1", Arrays.asList(1, 2, 3));
testMap.put("2", Arrays.asList(2, 3, 4));
String result = JsonUtil.obj2String(testMap);
// {"1":[1,2,3],"2":[2,3,4]}
System.out.println(result);
Map<String, List<Integer>> finalMap = JsonUtil.string2Obj(result, Map.class);
// {1=[1, 2, 3], 2=[2, 3, 4]}
System.out.println(finalMap);
}
到现在为止,你可以用这3个函数进行序列化和反序列化操作
/** 将对象转为json */
public static <T> String obj2String(T obj)
/** 将对象转为json,并格式化显示 */
public static <T> String obj2StringPretty(T obj)
/** 将json转为对象 */
public static <T> T string2Obj(String str, Class<T> clazz)
可能你还看过其他类型的解析方式,如下所示,但是没有必要,上面3个函数完全能满足你的需求,我这里演示一下
方式2
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 : objectMapper.readValue(str,typeReference));
} catch (Exception e) {
log.warn("Parse String to Object error",e);
return null;
}
}
@Test
public void string2Obj3() throws Exception {
Student student1 = new Student();
student1.setAge(10);
student1.setName("name1");
student1.setProfileImageUrl("link1");
Student student2 = new Student();
student2.setAge(20);
student2.setName("name2");
student2.setProfileImageUrl("link2");
List<Student> studentList = new ArrayList<>();
studentList.add(student1);
studentList.add(student2);
String result = JsonUtil.obj2String(studentList);
// [{"name":"name1","age":10,"profileImageUrl":"link1"},{"name":"name2","age":20,"profileImageUrl":"link2"}]
System.out.println(result);
List<Student> finalList = JsonUtil.string2Obj(result, new TypeReference<List<Student>>() {});
// [{name=name1, age=10, profileImageUrl=link1}, {name=name2, age=20, profileImageUrl=link2}]
System.out.println(finalList);
}
方式3
public static <T> T string2Obj(String str, Class<?> collectionClass, Class<?>... elementClasses){
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass,elementClasses);
try {
return objectMapper.readValue(str,javaType);
} catch (Exception e) {
log.warn("Parse String to Object error",e);
return null;
}
}
@Test
public void string2Obj4() throws Exception {
Student student1 = new Student();
student1.setAge(10);
student1.setName("name1");
student1.setProfileImageUrl("link1");
Student student2 = new Student();
student2.setAge(20);
student2.setName("name2");
student2.setProfileImageUrl("link2");
List<Student> studentList = new ArrayList<>();
studentList.add(student1);
studentList.add(student2);
String result = JsonUtil.obj2String(studentList);
// [{"name":"name1","age":10,"profileImageUrl":"link1"},{"name":"name2","age":20,"profileImageUrl":"link2"}]
System.out.println(result);
List<Student> finalList = JsonUtil.string2Obj(result, List.class, Student.class);
// [{name=name1, age=10, profileImageUrl=link1}, {name=name2, age=20, profileImageUrl=link2}]
System.out.println(finalList);
}
常用注解及配置
@JsonIgnore忽略属性
@Data
public class Student {
/** 名字 */
private String name;
/** 年龄 */
private Integer age;
/** 头像 */
@JsonIgnore
private String profileImageUrl;
}
@Test
public void jsonIgnore() throws Exception {
Student student = new Student();
student.setAge(10);
student.setName("name");
student.setProfileImageUrl("link");
String result = JsonUtil.obj2String(student);
// {"name":"name","age":10}
System.out.println(result);
String str = "{"name":"name","age":10,"profileImageUrl":"link"}";
Student student1 = JsonUtil.string2Obj(str, Student.class);
// Student(name=name, age=10, profileImageUrl=null)
System.out.println(student1);
}
@JsonProperty
当Json的属性值和Java的属性值不一样时,会映射失败,用这个注解指定映射关系,在属性上用这个注解,则序列化和反序列化都会用这个值。如果序列化和反序列化的属性不一致,可以在get方法或者set方法上用这个注解,set方法影响反序列化,get方法影响序列化。
去掉@Data注解
public class Student {
/** 名字 */
private String name;
/** 年龄 */
private Integer age;
/** 头像 */
private String profileImageUrl;
@JsonProperty("getImage")
public String getProfileImageUrl() {
return profileImageUrl;
}
@JsonProperty("setImage")
public void setProfileImageUrl(String profileImageUrl) {
this.profileImageUrl = profileImageUrl;
}
}
@Test
public void jsonProperty() throws Exception {
String str = "{"name":"name","age":10,"setImage":"link"}";
Student student1 = JsonUtil.string2Obj(str, Student.class);
// name
System.out.println(student1.getName());
// 10
System.out.println(student1.getAge());
// link
System.out.println(student1.getProfileImageUrl());
// {"name":"name","age":10,"getImage":"link"}
System.out.println(JsonUtil.obj2String(student1));
}
@JsonFormat
日期格式化注解,不再演示
@JsonIgnoreProperties(ignoreUnknown = true)
如果json字符串中的属性个数小于java对象中的属性个数,可以顺利转换,java中多的那个属性为null
如果json字符串中出现java对象中没有的属性,则在将json转换为java对象时会报错:Unrecognized field, not marked as ignorable
解决方法1: 在目标对象的类级别上添加注解:@JsonIgnoreProperties(ignoreUnknown = true)
解决方法2:
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
//忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
这样就不用在目标类上加@JsonIgnoreProperties属性了,体现了全局配置的优势,配置项很多,包括格式化显示日期等,不再详细介绍,百度配置即可
用Tree Mode方式解析JSON
除了将json转为对象外,还可以用Tree Mode方式解析JSON,全程无脑操作,除了一些特别复杂的JSON,或者只取JSON中的一部分,千万不要用这种二B方式解析JSON。正确的方式是将JSON直接转为对象。我这里演示一下解析的方式
{
"name": "zhansan",
"age": 100,
"schools": [
{
"name": "tsinghua",
"location": "beijing"
},
{
"name": "pku",
"location": "beijing"
}
]
}
@Test
public void parseJson() throws Exception {
String jsonStr = "{"name":"zhansan","age":100,"schools":[{"name":"tsinghua","location":"beijing"},{"name":"pku","location":"beijing"}]}";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(jsonStr);
String name = jsonNode.get("name").asText();
int age = jsonNode.get("age").asInt();
// name is zhansan age is 100
System.out.println("name is " + name + " age is " + age);
JsonNode schoolsNode = jsonNode.get("schools");
for (int i = 0; i < schoolsNode.size(); i++) {
String schooleName = schoolsNode.get(i).get("name").asText();
String schooleLocation = schoolsNode.get(i).get("location").asText();
// schooleName is tsinghua schooleLocation is beijing
// schooleName is pku schooleLocation is beijing
System.out.println("schooleName is " + schooleName + " schooleLocation is " + schooleLocation);
}
}
- 经验分享:社会工程学数据库搭建TIPS
- 过时但仍值得学习的选项卡TabHost
- 你所不知道的渗透测试:应用虚拟化的攻防
- C++中const小结
- 很多人不知道还有这个——搜索框组件SearchView
- 免费主题暗藏后门,波及WordPress等知名CMS系统
- 揭秘:针对PoS机的恶意软件工具箱
- 屏幕宽高不够,滚动视图ScrollView来凑
- 结合中间人攻击,Pidgin鸡肋漏洞变废为宝
- 日历视图CalendarView和定时器Chronometer
- 不用Linux也可以的强大文本处理方法
- 虚函数与虚继承寻踪
- AnalogClock、DigitalClock和TextClock时钟组件
- Sqlmap联合Nginx实现“地毯式”检测网站SQL注入漏洞
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一次性把所有普通和经典的网页布局讲得通通透透的,多图预警,建议收藏
- Github标星 8K+,免费又好用的Redis客户端工具!
- Python判断字符串是否包含特定子串的7种方法
- 用后台开发的逻辑理念学习VUE
- 进程管理-Linux每日一练(6)
- AkShare-能源数据-碳排放-国际行情
- Linux 【Shell脚本经典案例】
- 【Vulnhub】SecTalks: BNE0x00 - Minotaur
- Spring Boot扩展机制 - Spring Factories
- Google Analytics上实施透明度和用户意见征求框架
- 浅析鸿蒙 JavaScript GUI 技术栈
- C#串口操作类,包括串口读写操作
- Go by Example 中文版: 时间
- Go by Example 中文版: 时间戳
- Day14.模块&包