Jackson 解析中遇到的坑
Publish date: Oct 59, 5119
Last updated: Oct 219, 21029
Last updated: Oct 219, 21029
问
继解决了 Gson 解析的错误问题之后,发现日志里又出现了诡异的现象。
首先看 ShellResult 类:
@Data
public class ShellResult {
private int retCode;
private String stderr;
private String stdout;
private String command;
public String getExecutionLog() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%n shell command[%s]", command));
sb.append(String.format("%n ret code: %s", retCode));
sb.append(String.format("%n stderr: %s", stderr));
sb.append(String.format("%n stdout: %s", stdout));
return sb.toString();
}
}
@Data 是 lombok 支持的注解,可以自动生成一系列 JavaBean 的方法。
其次,看日志:
注意,诡异的现象发生了:executionLog 字段从哪来的?
答
查看代码
这一段日志的打印语句是:
String jsonData = JSONObjectUtil.toJsonString(result.getData());
logger.debug(String.format("Receive async VmAgent response success: [url:%s taskUuid:%s content:%s]", baseUrl, taskUuid, jsonData));
这里的 jsonData 从 result.getData() 中获取的,这个值是从 VmAgent 发送回调请求得到的。
那么,需要查看 VmAgent 端的代码发送的数据是什么?
log.debug(String.format("Reply msg : [name:%s content:%s]", reply.getClass().getSimpleName(), JsonUtils.objectToJson(reply)));
注意到,这里使用了 JsonUtils.objectToJson()
方法
跟进 JsonUtils 的源码:
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonUtils {
private static ObjectMapper mapper = new ObjectMapper();
public static String objectToJson(Object content) {
try {
return mapper.writeValueAsString(content);
} catch (IOException e) {
throw new CloudRuntimeException(e);
}
}
}
这个类中使用了 jackson 的 ObjectMapper 类的 writeValueAsString()
方法
我将这段代码抽出来,写了一个 Demo 运行了下:
public class Test {
public static void main(String[] args) {
ShellResult shellResult = new ShellResult();
shellResult.setRetCode(0);
shellResult.setStdout("stdout");
shellResult.setStderr("stderr");
shellResult.setCommand("command");
System.out.println(shellResult);
System.out.println(JsonUtils.objectToJson(shellResult));
}
}
运行结果如下:
ShellResult(retCode=0, stderr=stderr, stdout=stdout, command=command)
{"retCode":0,"stderr":"stderr","stdout":"stdout","command":"command","executionLog":"\n shell command[command]\n ret code: 0\n stderr: stderr\n stdout: stdout"}
解决之道
ShellResult 类的 getExecutionLog()
方法被解析成了字段,算是一个陷阱吧。
解决方案有两种:
方法1
直接把 getExecutionLog()
方法名改掉,不要 get 开头,不优雅。
方法2
在 getExecutionLog() 方法加个 jackson 提供的注解 @JsonIgnore
,如下:
@JsonIgnore
public String getExecutionLog() {
...
}
优雅解决。