Jackson:如何去除JSON输出中冒号左侧的空格
解决Jackson生成JSON时键与冒号间多余空格的问题
当前生成的JSON存在键名与冒号之间多一个空格的问题,示例如下:
[ { "satelliteId" : 1000, "severity" : "RED HIGH", "component" : "TSTAT", "timestamp" : "2018-01-01T23:01:38.001Z" }, { "satelliteId" : 1000, "severity" : "RED LOW", "component" : "BATT", "timestamp" : "2018-01-01T23:01:09.521Z" } ]
对应的生成代码(注释已转为中文):
import java.io.IOException; import java.time.Instant; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ObjectMapper; public class FormatAlerts { List<Message> alerts = new ArrayList<>(); public FormatAlerts(List<Message> alerts){ this.alerts = alerts; } public String formatAlerts(){ String formattedAlerts = null; ObjectMapper om = new ObjectMapper(); ArrayNode arrayNode = om.createArrayNode(); // 创建自定义格式化器,调整括号和大括号的缩进量 String indent = String.format("%-4s",""); DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(indent, DefaultIndenter.SYS_LF); DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); printer.indentObjectsWith(indenter); printer.indentArraysWith(indenter); try { for (Message m : alerts) { // 格式化时间 Instant t = Instant.ofEpochMilli(m.getEpochTime()); m.setTimestamp(t.toString()); // 将告警格式化为JSON String alert = om.writer(printer).writeValueAsString(m); // String alert = om.writerWithDefaultPrettyPrinter().writeValueAsString(m); ObjectNode obj = om.readValue(alert, ObjectNode.class); arrayNode.add(obj); formattedAlerts = om.writer(printer).writeValueAsString(arrayNode); // formattedAlerts = om.writerWithDefaultPrettyPrinter().writeValueAsString(arrayNode); } } catch (JsonProcessingException jpe) { jpe.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return formattedAlerts; } }
解决方案
问题根源在于DefaultPrettyPrinter的默认配置:它会在键和冒号之间添加空格(默认分隔符是": ")。要去掉这个空格,只需修改DefaultPrettyPrinter的objectFieldValueSeparator属性为":"即可。
同时原代码存在两处可优化点:
- 字符串格式化语句缺少闭合引号,需修正
- 循环内重复生成整个数组的JSON字符串,效率低下,建议循环仅添加节点,最后统一生成结果
修改后的完整代码:
import java.io.IOException; import java.time.Instant; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.ObjectMapper; public class FormatAlerts { List<Message> alerts = new ArrayList<>(); public FormatAlerts(List<Message> alerts){ this.alerts = alerts; } public String formatAlerts(){ String formattedAlerts = null; ObjectMapper om = new ObjectMapper(); ArrayNode arrayNode = om.createArrayNode(); // 创建自定义格式化器,调整括号和大括号的缩进量 String indent = String.format("%-4s",""); DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(indent, DefaultIndenter.SYS_LF); DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); // 移除键与冒号之间的空格 printer.objectFieldValueSeparator(":"); printer.indentObjectsWith(indenter); printer.indentArraysWith(indenter); try { for (Message m : alerts) { // 格式化时间 Instant t = Instant.ofEpochMilli(m.getEpochTime()); m.setTimestamp(t.toString()); // 直接将对象转为ObjectNode,避免序列化后再反序列化的冗余操作 ObjectNode obj = om.valueToTree(m); arrayNode.add(obj); } // 最后统一生成格式化后的JSON,提升效率 formattedAlerts = om.writer(printer).writeValueAsString(arrayNode); } catch (JsonProcessingException jpe) { jpe.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return formattedAlerts; } }
修改后生成的JSON会符合预期,键与冒号间无多余空格,同时保留原有缩进格式:
[ { "satelliteId": 1000, "severity": "RED HIGH", "component": "TSTAT", "timestamp": "2018-01-01T23:01:38.001Z" }, { "satelliteId": 1000, "severity": "RED LOW", "component": "BATT", "timestamp": "2018-01-01T23:01:09.521Z" } ]
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

