You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:30:44