This is the 30th day of my participation in the Wenwen Challenge
The business scenario
In the process of device communication service development, the following scenarios are generated:
Device one detects the message -> sends MQTT details -> Device two receives the message and processes it
In this process, Jackson is used to handle the conversion between data and JSON strings
This is where the problem arises
Analysis of the
In the message entity, we have a setter method like this:
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()); }}Copy the code
When Jackson parses the JSON string, he calls the setter method of the entity class. If the json form is {“names”: null}, the null pointer exception will be thrown on the second line of the setter method
plan
There are three ways to solve the problem:
- Modifying setter methods
- No NULL value is passed
- Configure Jackson to automatically ignore null values
Modifying setter methods
We just need to do a null check, which is 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()); }); }}Copy the code
No NULL value is passed
If the conversion process can be controlled
We can manually modify the pass-value logic to add default values and so on
Eliminate null values in JSON
Configure Jackson to automatically ignore null values
First, let’s show you how we converted 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 conversion failed", e); }}}Copy the code
We can add the following initialization configuration to prevent null problems:
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 conversion failed", e); }}}Copy the code
Configure (jsonParser.feature.allow_comments, true)
Json allows annotation formats, but of course, converted data is not affected
conclusion
Considering the robustness of the program, I recommend using both the first method and the third method