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

Spring返回application/x-ndjson如何将每个JSON对象调整为单行格式

解决Spring WebFlux NDJSON条目多行格式化问题

问题原因

当前Jackson序列化单个对象时启用了美化输出(pretty-print),而NDJSON规范要求每个条目必须是单行JSON字符串,每行之间用换行符分隔,因此需要针对application/x-ndjson类型的响应单独配置压缩序列化规则。

解决方案

方案1:全局关闭Jackson美化输出(最简单,适合全项目不需要JSON美化的场景)

直接在项目配置文件中添加以下配置即可:

# application.yml
spring:
  jackson:
    serialization:
      indent-output: false

properties格式对应配置:

# application.properties
spring.jackson.serialization.indent-output=false

方案2:单独为NDJSON配置序列化规则(推荐,不影响普通JSON接口的美化输出)

如果你的项目中普通application/json接口仍需要保留美化输出,只需自定义NDJSON专用的HTTP消息编码器:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
public class NdjsonSerializationConfig implements WebFluxConfigurer {

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        // 创建NDJSON专用ObjectMapper,强制关闭美化输出
        ObjectMapper ndjsonObjectMapper = new ObjectMapper()
                .disable(SerializationFeature.INDENT_OUTPUT);
        
        // 注册NDJSON类型的专用编码器
        configurer.defaultCodecs().jackson2JsonEncoder(
                new Jackson2JsonEncoder(ndjsonObjectMapper, 
                        MediaType.APPLICATION_NDJSON, 
                        new MediaType("application", "x-ndjson"))
        );
    }
}

配置完成后,请求Accept: application/x-ndjson时会自动使用压缩序列化,普通JSON请求不受影响,输出效果如下:

{"some":"thing"}
{"some":"other"}

方案3:接口层面手动处理(适合仅单个接口需要NDJSON输出的场景)

如果不想修改全局配置,也可以在对应接口手动序列化每个元素为单行字符串:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
public class SomeController {
    private final ObjectMapper ndjsonObjectMapper;

    public SomeController(ObjectMapper objectMapper) {
        // 复制全局ObjectMapper配置后关闭美化输出,避免影响全局逻辑
        this.ndjsonObjectMapper = objectMapper.copy().disable(SerializationFeature.INDENT_OUTPUT);
    }

    @GetMapping(produces = {
            MediaType.APPLICATION_JSON_VALUE,
            MediaType.APPLICATION_NDJSON_VALUE
    })
    public Flux<String> read() {
        // 替换为你实际的业务数据源
        Flux<Some> source = getFluxDataSource();
        return source.map(item -> {
            try {
                // 手动序列化为单行JSON,末尾加换行符符合NDJSON规范
                return ndjsonObjectMapper.writeValueAsString(item) + "\n";
            } catch (JsonProcessingException e) {
                throw new RuntimeException("NDJSON序列化失败", e);
            }
        });
    }
}

内容的提问来源于stack exchange,提问作者Jin Kwon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:15:03