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
相关产品推荐
相关产品推荐

