如何使用Jackson Mapper序列化时格式化含换行的字段值
问题
我现在用Jackson将Java对象序列化为JSON并打印到控制台,其中field2字段包含换行内容(类似错误堆栈信息),但输出时该字段的换行符被转义为\r\n,可读性较差。我期望输出时field2的内容按实际换行显示(如示例中的预期输出),同时保持JSON整体格式化,现询问实现该需求的方法,以及是否存在其他实现方式(我混淆了是否需要在反序列化时实现该效果)。
示例代码:
package goal.test; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class TestClass { String field1 = "hello"; String field2 = "hi\r\ntest"; public String getField1() { return field1; } public void setField1(String field1) { this.field1 = field1; } public String getField2() { return field2; } public void setField2(String field2) { this.field2 = field2; } public static void main(String[] args) throws JsonProcessingException { whatIsPossibleNow(); whatINeed(); } static void whatIsPossibleNow() throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(new TestClass()); System.out.println(result); /** * 当前输出结果 * { * "field1" : "hello", * "field2" : "hi\r\ntest" * } */ } static void whatINeed() throws JsonProcessingException { TestClass obj = new TestClass(); /** * 期望输出:field2的内容也按换行显示 * { * "field1" : "hello", * "field2" : "hi * test" * } * 效果和直接打印field2一致 */ System.out.println(obj.getField2()); } static void howCouldBe() throws JsonProcessingException { /** * 如何实现这个效果? */ ObjectMapper objectMapper = new ObjectMapper(); // 这里的prettyPrint()是错误写法,实际不存在 // objectMapper.writeValueAsString(new TestClass()).prettyPrint(); } }
解决方案
方法1:自定义PrettyPrinter
Jackson默认的DefaultPrettyPrinter会转义字符串中的换行符,我们可以自定义一个PrettyPrinter,跳过对换行符的转义,同时保留JSON的整体格式化结构。需要注意手动处理字符串中的双引号转义,避免破坏JSON格式。
代码示例:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.util.DefaultPrettyPrinter; // 新增实现方法 static void useCustomPrettyPrinter() throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); // 自定义PrettyPrinter DefaultPrettyPrinter customPrinter = new DefaultPrettyPrinter() { @Override public void writeString(String value, JsonGenerator g) throws IOException { // 转义字符串中的双引号,避免破坏JSON结构 String escapedValue = value.replace("\"", "\\\""); // 直接写入原始字符串(包含换行),用双引号包裹 g.writeRawValue("\"" + escapedValue + "\""); } }; String result = objectMapper.writer(customPrinter).writeValueAsString(new TestClass()); System.out.println(result); }
调用这个方法后,输出会符合预期:
{ "field1" : "hello", "field2" : "hi test" }
方法2:序列化后替换转义字符
如果不想自定义Printer,可以先正常生成格式化后的JSON,再将字符串中的\r\n转义序列替换为实际换行符。这种方法更简单,但要注意仅替换字符串内部的转义,避免影响JSON本身的结构换行。
代码示例:
static void postProcessJsonString() throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); // 先生成正常格式化的JSON String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(new TestClass()); // 将转义的\r\n替换为系统默认换行符 String readableJson = formattedJson.replace("\\r\\n", System.lineSeparator()); System.out.println(readableJson); }
注意:如果原字符串中本身包含\\r\\n(即用户输入的就是转义后的换行符),这种方法会错误地将其替换为实际换行,适合确定原字符串只有真实换行的场景。
关于反序列化的说明
你不需要在反序列化阶段处理这个需求。Jackson在反序列化时,会自动将JSON中的\r\n转义序列还原为字符串中的实际换行符。你的需求是提升序列化输出的可读性,所有处理都应该在序列化阶段完成。
内容的提问来源于stack exchange,提问作者Vivek Adhikari
相关产品推荐
相关产品推荐

