Jackson的序列化及反序列化【@JsonValue及@JsonCreator注解】

2024-04-14 15:18

本文主要是介绍Jackson的序列化及反序列化【@JsonValue及@JsonCreator注解】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Jackson的序列化

@JsonValue注解

@JsonValue 可以用在get方法或者属性字段上,一个类只能用一个,当加上@JsonValue注解时,序列化时只返回这一个字段的值,而不是这个类的属性键值对。

Teacher.class

package org.zpli.springdemo.bean;import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.Setter;/*** created at 2021/6/3 3:38 下午** @author somnuszpli*/
@Setter
@Getter
public class Teacher {// @JsonValueString name;int age;String address;}

测试方法:

@Test
public void test2() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();Teacher teacher = new Teacher();teacher.setName("somnuszpli");teacher.setAge(24);teacher.setAddress("China");String teacherStr = mapper.writeValueAsString(teacher);System.out.println(teacherStr);
}

输出结果:

{"name":"somnuszpli","age":24,"address":"China"}

在Teacher类的name属性上添加@JsonValue 注解

package org.zpli.springdemo.bean;import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.Setter;/*** created at 2021/6/3 3:38 下午** @author somnuszpli*/
@Setter
@Getter
public class Teacher {@JsonValueString name;int age;String address;}

运行测试方法,输出结果为:

"somnuszpli"

Jackson的反序列化

一、Jackson反序列化过程做了什么?

对于Jackson的JSON数据格式,反序列化过程就是将JSON字符串反序列化为java 对象

ObjectMapper mapper = new ObjectMapper();//将JSON字符串反序列化为java对象
String jsonInString = "{\"name\":\"乔丹\",\"age\":45,\"hobbies\":[\"高尔夫球\",\"棒球\"]}";
PlayerStar jordan = mapper.readValue(jsonInString, PlayerStar.class);System.out.println(jordan);

默认情况下,Jackson在反序列化过程中调用了哪些函数,给大家介绍一下

  • 首先调用反序列化的目标类PlayerStar的无参构造函数,构造一个java对象
  • 然后调用该类的成员变量的set方法,为该对象的每一个成员变量赋值。

所以默认情况下,一个Java类使用Jackson做反序列化,必须有public无参构造函数(java中不写也默认有),必须有成员变量的set方法。

二、@JsonCreator注解

默认情况下,Jackson的反序列化过程是上面描述的那样,默认选择类的无参构造函数创建类对象并使用setter方法给属性赋值,当没有无参构造函数时会报错。除此之外,我们还可以使用@JsonCreator注解自定义反序列化的过程,在我们自定义的反序列化函数里面,我们有更强的灵活性,可以完成更多的非规定动作。使用@JsonCreator注解的参数前面需要加上@JsonProperty,否则会报错。一共有两种自定义反序列化渠道:

  • @JsonCreator注解加在构造方法上
  • @JsonCreator注解加在工厂静态方法上

使用了@JsonCreator注解之后,将使用该注解标注的方法进行反序列化对象的构造,默认的使用无参构造函数及set方法进行反序列化的过程失效。

2.1.@JsonCreator注解加在构造方法上

该PlayerStar对应的JSON字符串是第一小节中的jsonInString。下文的构造函数,你希望将哪些属性值赋值给java 对象的成员变量,你就使用@JsonProperty("salary")去定义它。

package org.zpli.springdemo.bean;import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** created at 2021/6/3 3:14 下午** @author somnuszpli*/
public class PlayerStar {private String name;private Integer age;private String[] hobbies;               // 业余爱好,数组private List<String> friends;           // 朋友private Map<String, BigDecimal> salary; // 年收入 Map//这段是我们的核心代码,使用JsonCreator注解说明该方法是反序列化构造方法。@JsonCreatorpublic PlayerStar(@JsonProperty("name") String name,@JsonProperty("age") Integer age,@JsonProperty("hobbies") String[] hobbies,@JsonProperty("friends") List<String> friends,@JsonProperty("salary") Map<String, BigDecimal> salary) {this.name = name;this.age = age;this.hobbies = hobbies;this.friends = friends;this.salary = salary;}@Overridepublic String toString() {return "PlayerStar{" +"name='" + name + '\'' +", age=" + age +", hobbies=" + Arrays.toString(hobbies) +", friends=" + friends +", salary=" + salary +'}';}
}

我们使用第一小节中的反序列化代码,将jsonInString反序列化构造PlayerStar对象,控制台输出结果如下(对象的toString()方法输出):

PlayerStar{name='乔丹', age=45, hobbies=[高尔夫球, 棒球], friends=null, salary=null}

@JsonCreator标注的构造方法里面下断点,也的确证明在java 对象反序列化构造的过程中使用的是该方法。

2.2.@JsonCreator注解加在工厂静态方法上

除了可以将@JsonCreator加在构造方法上,还可以使用静态工厂函数反序列化构造java对象。使用方法如下:

package org.zpli.springdemo.bean;import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** created at 2021/6/3 3:14 下午** @author somnuszpli*/
public class PlayerStar {private String name;private Integer age;private String[] hobbies;               // 业余爱好,数组private List<String> friends;           // 朋友private Map<String, BigDecimal> salary; // 年收入 Map@JsonCreatorpublic static PlayerStar createPlayer(@JsonProperty("name") String name,@JsonProperty("age") Integer age,@JsonProperty("hobbies") String[] hobbies,@JsonProperty("friends") List<String> friends,@JsonProperty("salary") Map<String, BigDecimal> salary) {PlayerStar player = new PlayerStar();  //new 一个java对象player.name = name;    //赋值player.age = age;player.hobbies = hobbies;player.friends = friends;player.salary = salary;return player;}@Overridepublic String toString() {return "PlayerStar{" +"name='" + name + '\'' +", age=" + age +", hobbies=" + Arrays.toString(hobbies) +", friends=" + friends +", salary=" + salary +'}';}
}

使用@JsonCreator注解加在工厂静态方法上,可以达到一样的反序列化效果。

三、@ConstructorProperties注解

@ConstructorProperties注解的作用和@JsonCreator注解起到的作用是一致的,但是它只能加在构造方法上,作为反序列化函数。但是它的语法更简洁,使用起来也更加方便,不用@JsonProperty注解。又提供了灵活性,我们可以在构造方法反序列化过程中,针对该对象做更多的非规定操作。

package org.zpli.springdemo.bean;import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.beans.ConstructorProperties;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** created at 2021/6/3 3:14 下午** @author somnuszpli*/
public class PlayerStar {private String name;private Integer age;private String[] hobbies;               // 业余爱好,数组private List<String> friends;           // 朋友private Map<String, BigDecimal> salary; // 年收入 Map@ConstructorProperties({"name", "age","hobbies", "friends","salary"})public PlayerStar(String name,Integer age,String[] hobbies,List<String> friends,Map<String, BigDecimal> salary) {this.name = name;this.age = age;this.hobbies = hobbies;this.friends = friends;this.salary = salary;}@Overridepublic String toString() {return "PlayerStar{" +"name='" + name + '\'' +", age=" + age +", hobbies=" + Arrays.toString(hobbies) +", friends=" + friends +", salary=" + salary +'}';}
}

使用@ConstructorProperties注解加在构造方法上,可以达到一样的反序列化效果。

这篇关于Jackson的序列化及反序列化【@JsonValue及@JsonCreator注解】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/903324

相关文章

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

Springboot中Jackson用法详解

《Springboot中Jackson用法详解》Springboot自带默认json解析Jackson,可以在不引入其他json解析包情况下,解析json字段,下面我们就来聊聊Springboot中J... 目录前言Jackson用法将对象解析为json字符串将json解析为对象将json文件转换为json

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

使用@Slf4j注解,log.info()无法使用问题

《使用@Slf4j注解,log.info()无法使用问题》在使用Lombok的@Slf4j注解打印日志时遇到问题,通过降低Lombok版本(从1.18.x降至1.16.10)解决了问题... 目录@Slf4androidj注解,log.info()无法使用问题最后解决总结@Slf4j注解,log.info(

spring—使用注解配置Bean

从Spring2.5开始,出现了注解装配JavaBean的新方式。注解可以减少代码的开发量,spring提供了丰富的注解功能,现在项目中注解的方式使用的也越来越多了。   ** 开启注解扫描          Spring容器默认是禁用注解配置的。打开注解扫描的方式主要有两种: <context:component-scan>组件扫描和<context:annotation

Python---文件IO流及对象序列化

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 前文模块中提到加密模块,本文将终点介绍加密模块和文件流。 一、文件流和IO流概述         在Python中,IO流是用于输入和输出数据的通道。它可以用于读取输入数据或将数据写入输出目标。IO流可以是标准输入/输出流(stdin和stdout),也可以是文件流,网络流等。

Spring Boot 注解探秘:HTTP 请求的魅力之旅

在SpringBoot应用开发中,处理Http请求是一项基础且重要的任务。Spring Boot通过提供一系列丰富的注解极大地简化了这一过程,使得定义请求处理器和路由变得更加直观与便捷。这些注解不仅帮助开发者清晰地定义不同类型的HTTP请求如何被处理,同时也提升了代码的可读性和维护性。 一、@RequestMapping @RequestMapping用于将特定的HTTP请求映射到特定的方法上

jquery 表单序列化

jQuery序列化表单的方法总结 现在这里贴出案例中静态的html网页内容: <!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><title>Title</title><script src="../js/jquery-3.2.1.js"></script></head><body><form method="post"

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1)getTransletInstance2)defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码,但由于defineClas

Redis缓存 自定义注解+aspect+反射技术实现

最近再给云随笔后台增加redis模块,突然发现spring-boot-starter-data-redis模块很不人性化,实现不了通用的方式,(当然,你也可以自己写个通用的CacheUtil来实现通用的方式),但由于本人非常的爱装逼,就在这里不讲解那种傻瓜式操作了,这里只讲干货,干到你不可置信的干货). 例如:这里我使用了它其中的RedisTemplate ,发现存到redis中后,数据