spring.jackson.serialization.INDENT_OUTPUT=true
将配置文件application.properties
中的内容进行修改。假设您正在使用Jackson进行序列化。
如果您使用的是早期版本的Spring Boot,则可以添加
http.mappers.json-pretty-print=true
这个解决方案仍然适用于Spring Boot 1.2,但是它已经被弃用,最终将完全删除。在启动时,日志中会收到一个弃用警告。
(使用spring-boot-starter-web
进行测试)
在我发布这个问题时,我已经有了一个答案,但我还是决定发布它,以防有更好的替代解决方案。这是我的经验:
首先要明确一件事,MappingJacksonHttpMessageConverter
期望您注入一个 Jackson ObjectMapper
实例,并对该实例进行 Jackson 配置(而不是通过 Spring 类)。
我认为只需执行以下操作即可:
创建一个 ObjectMapperFactoryBean
实现,允许我自定义注入到 MappingJacksonHttpMessageConverter
中的 ObjectMapper
实例。例如:
<bean id="jacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<bean class="com.foo.my.ObjectMapperFactoryBean">
<property name="prettyPrint" value="${json.prettyPrint}"/>
</bean>
</property>
</bean>
然后,在我的ObjectMapperFactoryBean
实现中,我可以这样做(正如在SO的其他地方记录的解决方案):
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, isPrettyPrint());
return mapper;
但它没有起作用。而且试图找出原因是一场噩梦。弄清楚Jackson的工作方式需要耐心和时间的考验。查看其源代码只会让你更加困惑,因为它使用过时和晦涩的配置形式(整数位掩码来开启/关闭功能?你在开玩笑吗?)。
我基本上不得不从头开始重新编写Spring的MappingJacksonHttpMessageConverter
,并重写其 writeInternal
实现如下:
@Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
JsonGenerator jsonGenerator =
getObjectMapper().getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
try {
if (this.prefixJson) {
jsonGenerator.writeRaw("{} && ");
}
if (isPrettyPrint()) {
jsonGenerator.useDefaultPrettyPrinter();
}
getObjectMapper().writeValue(jsonGenerator, o);
}
catch (JsonGenerationException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
}
我在现有实现的基础上添加的唯一内容是以下代码块:
if (isPrettyPrint()) {
jsonGenerator.useDefaultPrettyPrinter();
}
isPrettyPrint()
只是我在MappingJacksonHttpMessageConverter
子类中添加的与JavaBeans兼容的getter和匹配的setter。
仅在完成这些步骤后,我才能基于${json.prettyPrint}
值(根据应用程序部署方式设置为属性)打开或关闭漂亮的打印。
希望这能对未来的某个人有所帮助!
如果你正在使用Jackson 2.0.0,你可以按照Les想要的方式进行操作。 我目前使用的是RC3,配置似乎正在按预期工作。
ObjectMapper jacksonMapper = new ObjectMapper();
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
翻译
{"foo":"foo","bar":{"field1":"field1","field2":"field2"}}
进入
{
"foo" : "foo",
"bar" : {
"field1" : "field1",
"field2" : "field2"
}
}
jacksonMapper.enable(SerializationFeature.INDENT_OUTPUT);
。 - gertas我可以建议采用这种方法,它适用于Spring 4.0.x甚至早期版本。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper());
return mappingJackson2HttpMessageConverter;
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objMapper = new ObjectMapper();
objMapper.enable(SerializationFeature.INDENT_OUTPUT);
return objMapper;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(mappingJackson2HttpMessageConverter());
}
}
感谢Willie Wheeler提供的解决方案:Willie Wheeler的Spring博客
objMapper.registerModule(new JavaTimeModule());
实现了这一点。欢迎其他人分享最佳实践。 - Chris Everitt如何使Jackson生成的JSON内容更易于阅读?
这里是一个简单的例子:
原始JSON输入:
{"one":"AAA","two":["BBB","CCC"],"three":{"four":"DDD","five":["EEE","FFF"]}}
Foo.java:
import java.io.FileReader;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
public class Foo
{
public static void main(String[] args) throws Exception
{
ObjectMapper mapper = new ObjectMapper();
MyClass myObject = mapper.readValue(new FileReader("input.json"), MyClass.class);
// this is Jackson 1.x API only:
ObjectWriter writer = mapper.defaultPrettyPrintingWriter();
// ***IMPORTANT!!!*** for Jackson 2.x use the line below instead of the one above:
// ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
System.out.println(writer.writeValueAsString(myObject));
}
}
class MyClass
{
String one;
String[] two;
MyOtherClass three;
public String getOne() {return one;}
void setOne(String one) {this.one = one;}
public String[] getTwo() {return two;}
void setTwo(String[] two) {this.two = two;}
public MyOtherClass getThree() {return three;}
void setThree(MyOtherClass three) {this.three = three;}
}
class MyOtherClass
{
String four;
String[] five;
public String getFour() {return four;}
void setFour(String four) {this.four = four;}
public String[] getFive() {return five;}
void setFive(String[] five) {this.five = five;}
}
输出:
{
"one" : "AAA",
"two" : [ "BBB", "CCC" ],
"three" : {
"four" : "DDD",
"five" : [ "EEE", "FFF" ]
}
}
如果这种方法不完全符合您的需求,可以搜索API文档v1.8.1中有关“pretty”的相关组件。如果您使用的是API版本2.x,则应查看更新的API 2.1.0文档。要启用漂亮的打印,需要添加并配置MappingJackson2HttpMessageConverter转换器。在生产环境中禁用漂亮的打印。
消息转换器配置
<mvc:annotation-driven>
<mvc:message-converters>
<bean id="jacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prettyPrint" value="${json.prettyPrint}" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
prettyPrint
渲染/防止的。我该如何实现呢? - mickeymoon根据baeldung的文章,使用Java 8可能是个不错的想法:
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
Optional<HttpMessageConverter<?>> converterFound;
converterFound = converters.stream().filter(c -> c instanceof AbstractJackson2HttpMessageConverter).findFirst();
if (converterFound.isPresent()) {
final AbstractJackson2HttpMessageConverter converter;
converter = (AbstractJackson2HttpMessageConverter) converterFound.get();
converter.getObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
converter.getObjectMapper().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}
我曾经遇到了使用自定义MappingJacksonHttpMessageConverter时的问题,尽管按照上述建议进行了操作,但在配置方面仍然遇到了一些困难。从代码角度来看,我完全按照上述方法进行了操作,但为了使其正常工作,我不得不在我的springapp-servlet.xml文件中添加以下配置。
希望这可以帮助其他想要实现相同功能的人。
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter" class="com.xxx.xxx.xxx.common.PrettyPrintMappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="prettyPrint" value="true" />
</bean>
我认为这是一个渲染问题,而不是REST服务的问题。
谁负责渲染?让该组件格式化JSON。也许可以有两个网址 - 一个用于生产环境,另一个用于开发环境。