jackson自定义反序列化器JsonDeserializer

这篇具有很好参考价值的文章主要介绍了jackson自定义反序列化器JsonDeserializer。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.JSON的序列化与反序列化

JSON序列化:将实体类对象转为JSON字符串
JSON反序列化:将JSON字符串转为实体类

2.jackson和gson

jackson作为Spring MVC和Spring Boot默认的JSON解析器,其与gson的工作原理不一样。
jackson通过调用实体类每个属性get/set方法进行注入,而gson则是通过设置每个属性为可访问后注入

jackson工作原理大致如下

//获取Class对象
Class<Order.OrderStatus> orderStatusClass = Order.OrderStatus.class;
//创建实例
Order.OrderStatus orderStatus=orderStatusClass.newInstance();
//获取实体类某个属性的get方法
Method setIsAllocated = orderStatusClass.getDeclaredMethod("setIsDelayed", Boolean.class);
//调用该方法,把值设置为true
setIsAllocated.invoke(orderStatus,true);

gson工作原理大致如下

//获取Class对象
Class<Order.OrderStatus> orderStatusClass = Order.OrderStatus.class;
//创建实例
Order.OrderStatus orderStatus=orderStatusClass.newInstance();
//获取Field对象
Field isDelayed = orderStatusClass.getDeclaredField("isDelayed");
//设置属性可写
isDelayed.setAccessible(true);
//注入值
isDelayed.set(orderStatus,true);

3.jackson的简单使用

ObjectMapper objectMapper=new ObjectMapper();
String json="{\"isAllocated\":true,\"isCheckout\":true}";
try {
        //将JSON字符串转为实体类
        orderStatus = objectMapper.readValue(json, Order.OrderStatus.class);
    } 
catch (JsonProcessingException e) {
        e.printStackTrace();
    }

4. 提出需求:将null值的字段解析为false

有一个实体类

public static class OrderStatus{
    private Boolean isDelayed;
    private Boolean isBulk;
    private Boolean isCheckout;
    private Boolean isAllocated;
    //构造器以及get和set方法省略.......
}

现在从前端传过来的是不定字段的JSON字符串,比如
"{"isAllocated":true,"isCheckout":true}",也可能是"{"isAllocated":true,"isBulk":true}"即JSON字符串中永远只有值为true的字段

如果使用readValue()默认的JSON解析器进行解析,得到的结果中不存在字段值为null,比如"{"isAllocated":true,"isCheckout":true}"的到的是
jackson自定义反序列化器JsonDeserializer

如果想将null值的字段解析为false应该如何处理

5.使用自定义JsonDeserializer

jackson库中有一个抽象类JsonDeserializer,其中要实现一个抽象方法deserialize

public abstract T deserialize(JsonParser var1, DeserializationContext var2) throws IOException, JacksonException;

我们定义自己的Deserializer并继承JsonDeserializer

public class OrderStatusDeserializer extends JsonDeserializer<Order.OrderStatus> {
    @Override
    public Order.OrderStatus deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
        //解析Json
        TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
        Set<String> fieldSet=new HashSet<>();
        //遍历Json字符串里面存在属性,并存在set中
        Iterator<String> iterator = treeNode.fieldNames();
        while(iterator.hasNext()){
            fieldSet.add(iterator.next());
        }
        //创建实例
        Order.OrderStatus orderStatus=new Order.OrderStatus();
        //获取Class实例
        Class<Order.OrderStatus> orderStatusClass = Order.OrderStatus.class;
        //获取Class的所有属性
        Field[] declaredFields = orderStatusClass.getDeclaredFields();
        for(Field field:declaredFields){
            field.setAccessible(true);
            //如果JSON字符串存在该属性则设置true
            if(fieldSet.contains(field.getName())) {
                try {
                    field.set(orderStatus,true);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            //否则设置false
            else {
                try {
                    field.set(orderStatus,false);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return orderStatus;

    }
}

OrderStatusDeserializer 进行注册

    @Test
    void testMyDeserializer() throws JsonProcessingException {
        String json="{\"isAllocated\":true,\"isCheckout\":true}";
        ObjectMapper objectMapper=new ObjectMapper();
        //通过simpleModule进行注册
        SimpleModule simpleModule=new SimpleModule();
        simpleModule.addDeserializer(Order.OrderStatus.class, new OrderStatusDeserializer());
        //注册simpleModule
        objectMapper.registerModule(simpleModule);
        Order.OrderStatus orderStatus = objectMapper.readValue(json, Order.OrderStatus.class);
        System.out.println(orderStatus);
    }

也可以通过注解进行注册

@JsonDeserialize(using= OrderStatusDeserializer.class)
    public static class OrderStatus{
        private Boolean isDelayed;
        private Boolean isBulk;
        private Boolean isCheckout;
        private Boolean isAllocated;
 }
    @Test
    void testMyDeserializer() throws JsonProcessingException {
        String json="{\"isAllocated\":true,\"isCheckout\":true}";
        ObjectMapper objectMapper=new ObjectMapper();
        //使用注解注册后直接调用即可
        Order.OrderStatus orderStatus = objectMapper.readValue(json, Order.OrderStatus.class);
        System.out.println(orderStatus);
    }

得到的结果为
jackson自定义反序列化器JsonDeserializer
可以看到:JSON字符串中不存在的字段,都设置为false了

6.另辟蹊径

前面提到jackson默认通过反射,使用get/set方法进行注入,那么在此之前必定会调用空参构造函数构造一个实例,如

//获取Class对象
Class<Order.OrderStatus> orderStatusClass = Order.OrderStatus.class;
//创建实例
Order.OrderStatus orderStatus=orderStatusClass.newInstance();

然后再调用JSON字符串中存在的字段的set方法。那么如果在构造器初始化时,默认设置每个属性都为false,然后任由jackson调用对应的set方法设置true,不也一样能达到同样的效果吗?

修改空参构造函数,另外取消自定义的JsonDeserializer

 public OrderStatus() {
        System.out.println("jackson调用了空参构造函数");
        this.isDelayed=false;
        this.isBulk=false;
        this.isCheckout=false;
        this.isAllocated=false;
    }

结果证明确实调用了空参构造,另外同样能实现将null设置为false
jackson自定义反序列化器JsonDeserializer文章来源地址https://www.toymoban.com/news/detail-457186.html

7. 总结

遇到问题先去看官方文档,如果文档中没有提到相关功能,看源码调试。另外也要对Java反射机制熟悉

到了这里,关于jackson自定义反序列化器JsonDeserializer的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • JackSon反序列化通杀

    JackSon反序列化通杀

    Springboot一般都会自带 JackSon 这个依赖包, JackSon 跟 Fastjson 有相同的功效 运行即可弹计算器 PoJoNode 类是继承 ValueNode , ValueNode 是继承 BaseJsonNode 类,我们看看 BaseJsonNode 类 它拥有 writeReplace 方法,有这个方法就意味着反序列化时不会走正常渠道,而是走这个 writeReplace 方法,

    2024年04月12日
    浏览(14)
  • jackson null值 序列化

    在Jackson中,序列化时将 null 值转换为字符串(例如,输出为 \\\"null\\\" 而不是忽略或输出 null )通常不是标准行为,但可以通过自定义序列化处理器来实现。 以下是一个简单的示例,演示如何创建一个自定义 JsonSerializer ,用于将所有类型的 null 值序列化为字符串 \\\"null\\\" : 全局注

    2024年01月18日
    浏览(13)
  • RabbitMQ 消息对象通过 Jackson 库消息转化器 序列化/反序列化 天坑!

    RabbitMQ 消息对象通过 Jackson 库消息转化器 序列化/反序列化 天坑!

    目录 1. 报错的背景 2. 问题分析 3. 最佳解决办法 a)使用 RabbitMQ 发送消息时,发送消息的类型为 MapString, Object,map 里面我 put 了一个 String, Long 类型,如下图: b)这里有一个前提:我清楚使用 org.springframework.amqp.rabbit.core.RabbitTemplate 来发送消息到 RabbitMQ 队列时,消息的序列

    2024年04月15日
    浏览(13)
  • Jackson--FastJson--XStream--代码执行&&反序列化

    2.0.0 = FasterXML jackson-databind Version = 2.9.10.2 不受影响版本 FasterXML jackson-databind = 2.8.11.5 FasterXML jackson-databind = 2.9.10.3 POC: String json = \\\"[\\\"org.apache.xbean.propertyeditor.JndiConverter\\\", {\\\"asText\\\":\\\"ldap://localhost:1389/Exploit\\\"}]\\\"; FasterXML jackson-databind 2.x 2.9.10.8 POC String payload = \\\"[\\\"com.oracle.wls.shaded.org.apa

    2024年02月08日
    浏览(34)
  • Redis添加LocalDateTime时间序列化/反序列化Java 8报‘jackson-datatype-jsr310’问题

    错误信息: 1、增加pom依赖 2、对应字段增加属性

    2024年02月11日
    浏览(9)
  • Jackson序列化Bean额外属性附加--@JsonAnyGetter、@JsonUnwrapped用户

    有一项工作,需要将数据从一个服务S中读取出来(得到的是一个JSON),将数据解析转换以后构造成一个数组的类型A的对象,写入到一个服务T中。 A.class 在发现需要增加一种类型A的字类型B,这个类型属性非常多(将近一百),在这种情形下,如果直接定义出类型B来,定义那

    2024年01月24日
    浏览(15)
  • Jackson-databind 反序列化漏洞(CVE-2017-7525、CVE-2017-17485)

    Jackson-databind 反序列化漏洞(CVE-2017-7525、CVE-2017-17485)

    Jackson-databind 支持 Polymorphic Deserialization 特性(默认情况下不开启),当 json 字符串转换的 Target class 中有 polymorph fields,即字段类型为接口、抽象类或 Object 类型时,攻击者可以通过在 json 字符串中指定变量的具体类型 (子类或接口实现类),来实现实例化指定的类,借助某些特

    2024年02月13日
    浏览(11)
  • 【Linux】自定义协议+序列化+反序列化

    【Linux】自定义协议+序列化+反序列化

    喜欢的点赞,收藏,关注一下把! 协议是一种 “约定”。在前面我们说过父亲和儿子约定打电话的例子,不过这是感性的认识,今天我们理性的认识一下协议。 socket api的接口, 在读写数据时,都是按 “字符串”(其实TCP是字节流,这里是为了理解) 的方式来发送接收的。如

    2024年04月08日
    浏览(11)
  • springboot对象序列化自定义序列化注解

    在开发中有时候会遇到一些内容返回时需要翻译,或者一些内容在序列化之前需要特殊处理(脱敏啥的)。 一般对单个属性可以直接用 jackson 的序列化注解对某个属性单独处理 com.fasterxml.jackson.databind.annotation.JsonSerialize(using= xxx.class) 但是直接使用不太灵活,可以进一步引入注

    2024年02月07日
    浏览(15)
  • jackjson自定义序列化和反序列化

    jackjson自定义序列化和反序列化

    JRT引用的jackjson作为json处理库。由于JRT.ORM要求表不用datetime类型,把日期和时间用Int存储,所以ORM要支持日期时间的转换。为什么要把日期时间不用datetime而用Int,比如日期:20240117,时间就是从0点到当前的秒数。因为不用datetime兼容性好,不会因为不同库datetime函数不同而要

    2024年01月18日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包