记录一次Jackson转换的错误处理

397 阅读2分钟

这是我参与更文挑战的第30天,活动详情查看: 更文挑战

业务场景

在进行设备通信业务开发的过程中, 会产生这样的场景:

设备一检测到信息->发送mqtt详细->设备二接收消息并处理

在这个过程中, 会利用Jackson处理数据与json字符串之间的转换

问题也就出现在这里

分析

在消息实体中, 我们有这样一个setter方法:

public class MqttInfo {
    private List<String> names;
    private List<String> suffixNames;
    
    public void setNames(List<String> names) {
        this.names = names;
        this.suffixNames = names.stream().filter(name -> name.contains("test")).collect(Collectors.toList());
    }
}

jackson在解析json字符串时, 会调用实体类的setter方法, 如果json形式为: {"names": null}, 在setter方法的第二行就会抛出空指针异常

方案

解决问题的方式总共有三种:

  1. 修改setter方法
  2. 不传递null值
  3. 配置jackson自动忽略null值

修改setter方法

我们只需要进行一个空值判断即可, 这里推荐使用Optional类哦:

public class MqttInfo {
    private List<String> names;
    private List<String> suffixNames;
    
    public void setNames(List<String> names) {
        this.names = names;
        Optional.ofNullable(names).ifPresent(data -> {
            this.suffixNames = data.stream().filter(name -> name.contains("test")).collect(Collectors.toList());
        });
    }
}

不传递null值

如果转换过程可控的话

我们可以通过手动修改传值逻辑, 会为其增加默认值等方法

消除掉json中的null值问题

配置jackson自动忽略null值

首先展示下我们转换json时的方式:

public class MqttUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();
    
    private static void sendMessage(MqttPahoMessageHandler handler, String topic, Object data) {
        try {
            String json = MAPPER.writeValueAsString(data);
            Message<String> mqttMessage = MessageBuilder.withPayload(json).setHeader(MqttHeaders.TOPIC, topic).setHeader(MqttHeaders.QOS, DEFAULT_QOS).build();
            handler.handleMessage(mqttMessage);
        } catch (JsonProcessingException e) {
            throw new MqttException("json转换失败", e);
        }
    }
}

我们可以增加如下初始化配置, 防止出现null值的问题:

public class MqttUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();
    
    static {
        MAPPER.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }
    
    private static void sendMessage(MqttPahoMessageHandler handler, String topic, Object data) {
        try {
            String json = MAPPER.writeValueAsString(data);
            Message<String> mqttMessage = MessageBuilder.withPayload(json).setHeader(MqttHeaders.TOPIC, topic).setHeader(MqttHeaders.QOS, DEFAULT_QOS).build();
            handler.handleMessage(mqttMessage);
        } catch (JsonProcessingException e) {
            throw new MqttException("json转换失败", e);
        }
    }
}

因为在测试时有注释出现, 所以笔者还增加MAPPER.configure(JsonParser.Feature.ALLOW_COMMENTS, true)

允许json中有注释格式, 当然, 转换后的数据不会受影响

总结

考虑到程序的健壮性, 笔者建议同时使用第一种方法和第三种方法进行处理