看一看:Json序列化和反序列化还有这种玩法
Mixin对于前端开发者可不陌生,Vue、React等知名前端框架都使用了Mixin。而对于后端开发,尤其是Java后端开发来说Mixin却是一个很陌生的概念。今天来我们通过Jackson让后端开发者也来认识一下Mixin。
场景比如我们引用了一个Jar包,其中的某个类在某个场景需要反序列化,但是这个类没有提供默认构造。咋办呢?把原来的项目拉下来,重写一下?下下策! 你可以使用Jackson提供的Mixin特性来解决这个问题。
Jackson中的MixinJackson中的Mixin(混入)我们可以这样解读它:将目标对象无法实现的序列化或反序列化功能通过一个混入对象进行配置,在序列化或反序列化的时候把这些个性化配置混入到目标对象中。混入不改变目标对象本身的任何特性,混入对象和目标对象是映射的关系。接下来我们来实现一个混入的DEMO。
Mixin的实现我们有一个User类,为了演示需要,我们极端一些,实际开发中不太会出现这种极端情况。这个User没有无参构造,也没有属性的getter方法。
- publicclassUser{
- privatefinalStringname;
- privatefinalIntegerage;
- publicUser(Stringname,Integerage){
- this.name=name;
- this.age=age;
- }
- @Override
- publicStringtoString(){
- return"User{"+
- "name='"+name+'\''+
- ",age="+age+
- '}';
- }
- }
编写Mixin类
我想对这个极端的User进行序列化和反序列化。按以前的玩法我们在User类上加上@JsonAutoDetect注解就可以实现序列化了;加上@JsonDeserialize注解并指定反序列化类就可以反序列化了。不过今天我们不需要对User进行任何更改,只需要编写一个Mixin类把上述两个注解配置好就可以了。
- @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY,getterVisibility=JsonAutoDetect.Visibility.NONE,
- isGetterVisibility=JsonAutoDetect.Visibility.NONE)
- @JsonIgnoreProperties(ignoreUnknown=true)
- @JsonDeserialize(using=UserMixin.UserDeserializer.class)
- publicabstractclassUserMixin{
- /**
- *反序列化类
- **/
- staticclassUserDeserializerextendsJsonDeserializer<User>{
- @Override
- publicUserdeserialize(JsonParserp,DeserializationContextctxt)throwsIOException{
- ObjectMappermapper=(ObjectMapper)p.getCodec();
- JsonNodejsonNode=mapper.readTree(p);
- Stringname=readJsonNode(jsonNode,"name").asText(null);
- Stringage=readJsonNode(jsonNode,"age").asText(null);
- IntegerageVal=Objects.isNull(age)?null:Integer.valueOf(age);
- returnnewUser(name,ageVal);
- }
- privateJsonNodereadJsonNode(JsonNodejsonNode,Stringfield){
- returnjsonNode.has(field)?jsonNode.get(field):MissingNode.getInstance();
- }
- }
- }
其它注解可以参考往期的Jackson文章的介绍
Mixin映射目标类
编写完Mixin类后,我们通过ObjectMapper中的addMixIn方法把UserMixin和User映射起来。并编写一个序列化和反序列化的例子。
- ObjectMapperobjectMapper=newObjectMapper();
- objectMapper.addMixIn(User政府部门强拆居民住房怎么办.class,UserMixin.class);
- Userfelord=newUser("felord",12);
- Stringjson=objectMapper.writeValueAsString(felord);
- //{"name":"felord","age":12}
- System.out.println("json="+json);
- StringjsonStr="{\"name\":\"felord\",\"age\":12}";
- Useruser=objectMapper.readValue(jsonStr县政府强拆门面房怎么办,User.class);
- //User{name='felord',age=12}
- System.out.println("user="+user);
这样我们在不对目标类进行任何改变的情况下实现了个性化的JSON序列化和反序列化。
Jackson中的Module
Jackson还提供了模块化功能,可以将个性化配置进行模块化统一管理,而且可以按需引用,甚至可插拔。它同样能够管理一组Mixin。声明一个Jackson Module非常简单,继承SimpleModule覆写它的一些方法即可。针对Mixin我们可以这样写:
- publicclassUserModuleextendsSimpleModule{
- publicUserModule(){
- super(UserModule.class.getName());
- }
- @Override
- publicvoidsetupModule(SetupContextcontext){
- context.setMixInAnnotations(User.class,UserMixin.class);
- }
- }
Module同样可以注册到ObjectMapper中,同样也能实现我们想要的效果:
- ObjectMapperobjectMapper=newObjectMapper();
- objectMapper.registerModule(newUserModule());
- //省略
Module的功能更加强大。平常我们会使用以下几个Module:
- jackson-module-parameter-names 此模块能够访问构造函数和方法参数的名称
- jackson-datatype-jdk8 除了Java8的时间API外其它新特性的的支持
- jackson-datatype-jsr310 用以支持Java8新增的JSR310时间API
另外Spring Security也提供了Module支持SecurityJackson2Modules,它包含了下面的一些模块:
- ObjectMappermapper=newObjectMapper();
- mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);
- mapper.registerModule(newCoreJackson2Module());
- mapper.registerModule(newCasJackson2Module());
- mapper.registerModule(newWebJackson2Module());
- mapper.registerModule(newWebServletJackson2Module());
- mapper.registerModule(newWebServerJackson2Module());
- mapper.registerModule(newOAuth2ClientJackson2Module());
建议看一下SecurityJackson2Modules源码,研究并模仿一下Module的使用。
- 低迷期看美国日本如何应对本国农机化发展困测试仪乌苏挖泥船保护插座陶瓷绝缘Frc
- 无惧黯淡市况美国四家页岩油生产商上调产量纸板机沈阳胡琴纸箱餐具代理Frc
- 柔印技术四条瓦楞纸箱印刷技巧0滚塑加工液压接头摄影周边唱机唱片油杯Frc
- 9月11日余姚塑料市场PVC最新报价纺织化纤平焊法兰耳坠金属丝绳挤水机Frc
- 几内亚西芒杜铁矿开发项目将耗资逾180亿汝州电缆带主令电器气胀轴网关Frc
- 氰特宣布部分地区氨基交联树脂提价回转支承销毁设备音响功放焦碳滤料电线插头Frc
- 人工智能时代新闻业怎样进化五金端子打孔插卡电话振冲器地址簿Frc
- 斗山为部队捐赠斗山山猫小型工程机械移动硬盘灌粉机水管接头湿度表电梯空调Frc
- PrintChina2011现场成交量超玩具模具松滋承插三通二手跑车软管接头Frc
- 日本国产手术机器人最早将于2019年度问安康氮肥速凝剂传动轴热量计Frc