@JsonCreator和@JsonValue

news/2025/2/15 5:24:12/

文章目录

  • 1、正常反序列化的过程
  • 2、@JsonCreator
  • 3、@JsonValue
  • 4、应用:枚举类中校验传参以及优化前后端数据交互
  • 5、补充:@ConstructorProperties

1、正常反序列化的过程

反序列化时,默认会调用实体类的无参构造来实例化一个对象,然后使用setter来初始化属性值。写点测试代码:

@AllArgsConstructor
@Data
public class Book {private String name;private Double price;}

测试下:

public class TestSome1 {@Testvoid testJson() throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();Book book = objectMapper.readValue("{\n" +"    \"name\":\"Java\",\n" +"    \"price\":666.00\n" +"}", Book.class);System.out.println(book);}
}

此时,运行会抛出InvalidDefinitionException:

在这里插入图片描述

2、@JsonCreator

@JsonCreator可用在:

  • 构造方法上
  • 静态的工厂方法上

加了@JsonCreator注解,该类的对象在反序列化时,就走有@JsonCreator注解的方法来反序列化,原先无参+set的过程失效。

上面的Book类,可改成:

//@AllArgsConstructor
@Getter
public class Book {private String name;private Double price;@JsonCreatorpublic Book(@JsonProperty("name") String name,@JsonProperty("price") Double price ){System.out.println("@JsonCreator生效");this.name = name;this.price = price+1;}}

上面的@JsonProperty注解就是指定传参名和对象属性关系的,有点像MyBatis的@Param

 public Book(@JsonProperty("name") String name,@JsonProperty("price") Double price ){

@JsonCreator放在静态方法上就是:

@AllArgsConstructor
@Getter
public class Book {private String name;private Double price;@JsonCreatorpublic static Book unSerialize(){System.out.println("正在反序列化成对象");return new Book("111",1.00);}}

以@JsonCreator放在构造方法上为例,再运行前面的单元测试,看下反序列化的效果:

在这里插入图片描述

3、@JsonValue

@JsonValue注解可用在:

  • get方法
  • 属性字段上

一个类只能用一个,加上这个注解时,该类的对象序列化时就会只返回这个字段的值做为序列化的结果。

比如一个枚举类的get方法上加上该注解,那么在序列化这个枚举类的对象时,返回的就是枚举对象的这个属性,而不是这个枚举对象的序列化json串。继续改造上面的Book类:

@AllArgsConstructor
@Getter
public class Book {//@JsonValue,加get方法或者这个属性上,都一样private String name;private Double price;@JsonCreatorpublic static Book doSerialize(){System.out.println("正在反序列化成对象");return new Book("111",1.00);}/*** 序列化时,序列化成我return的值,即当前对象的name属性*/@JsonValuepublic String getName(){return this.name;}
}

单元测试中看下效果:

public class TestSome1 {@Testvoid testJson() throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();Book book = objectMapper.readValue("{\n" +"    \"name\":\"Java\",\n" +"    \"price\":666.00\n" +"}", Book.class);System.out.println(book);System.out.println("=======");//序列化System.out.println(objectMapper.writeValueAsString(book));}
}

在这里插入图片描述

4、应用:枚举类中校验传参以及优化前后端数据交互

比如定义一个排序字段的枚举类,排序字段要拼到mapper层的SQL,所以其传参的合法性必须校验,每次在Service层校验,很繁琐。引入@JsonCreator:

@AllArgsConstructor
@Getter
public enum OrderFieldEnum {CREATE_TIME("createTime","create_time"),USER_NAME("userName","user_name");private final String value;private final String field;private static final Map<String,OrderFieldEnum> map = new HashMap<>(3);@JsonCreatorpublic static OrderFieldEnum unSerializer(String value){//把以value为key,以枚举对象为value,存进mapif(map.isEmpty()){for (OrderFieldEnum fieldEnum : OrderFieldEnum.values()) {map.put(fieldEnum.value,fieldEnum);}}//map中找不到就是超出范围if(!map.containsKey(value)){throw new RuntimeException("超出范围");}return map.get(value);}@JsonValuepublic String getValue(){return this.value+"@JsonValue";   //这里刻意加个@JsonValue,方便后面验证序列化效果。return this.value就行。}}

此时,前端传个dto(json)过来,dto里有个参数的类型是枚举类型,反序列化json成dto对象时,枚举类型的属性也会反序列化,上面@JsonCreator定义的unSerializer方法执行,就会完成参数合法性校验,Service层省事了。至于序列化:

@JsonValue
public String getValue(){return this.value;
}

比如需要返给前端枚举值展示下拉框,就直接Vo里就直接List<Enum> enumList,而不用定义个List<String> enumList,再反复getValue:

enumList.add(ENUM1.getValue)  
enumList.add(ENUM2.getValue)
...

因为返给前端时,Vo对象序列化,里面的一个个枚举对象也序列化,而JsonValue已经指定了序列化枚举对象时就把它的value返回就行。写个简单接口看下效果,定义个dto:

@Data
public class JsonDto {private String id;private OrderFieldEnum orderField;
}

Service层demo:

@Service
public class MyService {public List<OrderFieldEnum> listValue(JsonDto dto){System.out.println(dto.getOrderField());//直`List<Enum>List<OrderFieldEnum> list = List.of(OrderFieldEnum.CREATE_TIME, OrderFieldEnum.USER_NAME);return list;}
}

controller:

@RestController
public class CodeController {@Resourceprivate MyService myService;@PostMapping("/test")public List<OrderFieldEnum> getStr(@RequestBody JsonDto dto){return myService.listValue(dto);}
}

异常传参时:

在这里插入图片描述

正常传参:

在这里插入图片描述

此时,不管枚举类型啥的,前端传个String就行。最后,注解的依赖坐标引对:

在这里插入图片描述

5、补充:@ConstructorProperties

在这里插入图片描述


http://www.ppmy.cn/news/1235351.html

相关文章

git提交日志管理命令

# 显示有变更的文件 $ git status# 显示当前分支的版本历史 $ git log# 显示commit历史&#xff0c;以及每次commit发生变更的文件 $ git log --stat# 搜索提交历史&#xff0c;根据关键词 $ git log -S [keyword]# 显示某个commit之后的所有变动&#xff0c;每个commit占据一行…

git操作分支命令

# 列出所有本地分支 $ git branch# 列出所有远程分支 $ git branch -r# 列出所有本地分支和远程分支 $ git branch -a# 新建一个分支&#xff0c;但依然停留在当前分支 $ git branch [branch-name]# 新建一个分支&#xff0c;并切换到该分支 $ git checkout -b [branch]# 新建一…

【搭环境】装Python3.8 open3d

先装Python3.8 方法一试了找不到Python3.8的库&#xff0c;所以用方法二装上了。 Python3加入环境变量 更改Python默认指向 open3d需要Python3.6以上&#xff0c;最好用Ubuntu18版本&#xff0c;我用的16版本。。

【nlp】2.8 注意力机制拓展

注意力机制拓展 1 注意力机制原理1.1 注意力机制示意图1.2 Attention计算过程1.3 Attention计算逻辑1.4 有无attention模型对比1.4.1 无attention机制的模型1.4.2 有attention机制的模型1 注意力机制原理 1.1 注意力机制示意图 Attention机制的工作原理并不复杂,我们可以用下…

2023上海小学生古诗文大会复赛(复选)在线模拟题库更新到503题

为了帮助参加2023年上海小学生古诗文大会复选&#xff08;复赛&#xff09;的孩子们更好地练习和备考&#xff0c;我这几天制作了一个在线练习的模拟题库。 这个在线模拟题对标市级比赛的形式和样式&#xff0c;具有以下特点和功能&#xff1a; 1、可以通过手机、电脑、平板&a…

解决mv3版本浏览器插件,不能注入js脚本问题

文章目录 背景引入ifream解决ifream和父页面完全跨域问题参考链接 背景 浏览器插件升级mv3版本后&#xff0c;不能再使用content_script内容脚本向原浏览器&#xff08;top&#xff09;注入script标签达到注入脚本的目的。浏览器认为插入未经审核的脚本是不安全的行为。 引入…

计网(复习自用)

计算机网络 1.概述 1.1概念 含义 计算机网络&#xff1a;是一个将分散的。具有独立功能的计算机系统&#xff0c;通过通信设备和线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。 简单点说&#xff0c;计算机网络是互联的&#xff0c;自治的计算机集…

OpenGL 绘制点与三角形(Qt)

文章目录 一、简介二、实现代码三、实现效果一、简介 这里对OpenGL中点与三角形相关绘制操作进行封装,方便后续点云数据与模型数据的渲染。 二、实现代码 这里我们先创建一个基类Drawable,后续的点、线、面等,均会继承该类: Drawable.h #ifndef DRAWABLE_H #define DRAWABL…