这是我参与更文挑战的第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方法的第二行就会抛出空指针异常
方案
解决问题的方式总共有三种:
- 修改setter方法
- 不传递null值
- 配置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中有注释格式, 当然, 转换后的数据不会受影响
总结
考虑到程序的健壮性, 笔者建议同时使用第一种方法和第三种方法进行处理