在使用Spring MVC进行REST时,您如何使Jackson能够预打印呈现的JSON?

时间:2020-12-26 21:44:19

While developing REST services using Spring MVC, I would like render JSON 'pretty printed' in development but normal (reduced whitespace) in production.

在使用Spring MVC开发REST服务时,我希望在开发中呈现JSON,但在生产中呈现为正常的(减少了空格)。

10 个解决方案

#1


36  

If you are using Spring Boot 1.2 or later the simple solution is to add

如果您正在使用Spring Boot 1.2或更高版本,简单的解决方案是添加

spring.jackson.serialization.INDENT_OUTPUT=true

to the application.properties file. This assumes that you are using Jackson for serialization.

给应用程序。属性文件。这假定您正在使用Jackson进行序列化。

If you are using an earlier version of Spring Boot then you can add

如果您使用的是较早版本的Spring Boot,那么您可以添加。

http.mappers.json-pretty-print=true

This solution still works with Spring Boot 1.2 but it is deprecated and will eventually be removed entirely. You will get a deprecation warning in the log at startup time.

这个解决方案仍然适用于Spring Boot 1.2,但它已被弃用,最终将被完全删除。在启动时,您将在日志中获得一个弃用警告。

(tested using spring-boot-starter-web)

(使用spring-boot-starter-web测试)

#2


31  

I had an answer when I posted this question, but I thought I'd post it anyway in case there are better alternative solutions. Here was my experience:

当我发布这个问题的时候,我得到了一个答案,但是我想我还是要发布它,以防有更好的替代解决方案。这是我的经验:

First thing's first. The MappingJacksonHttpMessageConverter expects you to inject a Jackson ObjectMapper instance and perform Jackson configuration on that instance (and not through a Spring class).

第一件事是第一次。MappingJacksonHttpMessageConverter期望您注入一个Jackson ObjectMapper实例并在该实例上执行Jackson配置(而不是通过Spring类)。

I thought it would be as easy as doing this:

我觉得这样做很简单:

Create an ObjectMapperFactoryBean implementation that allows me to customize the ObjectMapper instance that can be injected into the MappingJacksonHttpMessageConverter. For example:

创建一个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>

And then, in my ObjectMapperFactoryBean implementation, I could do this (as has been documented as a solution elsewhere on SO):

然后,在我的ObjectMapperFactoryBean实现中,我可以这样做(正如其他地方的解决方案所记录的那样):

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, isPrettyPrint());
return mapper;

But it didn't work. And trying to figure out why is a nightmare. It is a major test of patience to figure Jackson out. Looking at its source code only confuses you further as it uses outdated and obtuse forms of configuration (integer bitmasks for turning on/off features? Are you kidding me?)

但它不工作。试图弄明白为什么这是一场噩梦。这是对杰克逊耐心的一次重大考验。查看它的源代码只会让您更加困惑,因为它使用过时的、迟钝的配置形式(用于打开/关闭特性的整数位掩码?)你在跟我开玩笑吧?)

I essentially had to re-write Spring's MappingJacksonHttpMessageConverter from scratch, and override its writeInternal implementation to be the following:

实际上,我必须从头重写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);
    }
}

The only thing I added to the existing implementation is the following block:

我在现有的实现中添加的唯一内容是:

if (isPrettyPrint()) {
    jsonGenerator.useDefaultPrettyPrinter();
}

isPrettyPrint() is just a JavaBeans compatible getter w/ matching setter that I added to my MappingJacksonHttpMessageConverter subclass.

isPrettyPrint()只是我添加到MappingJacksonHttpMessageConverter子类的一个javabean兼容的getter /匹配setter。

Only after jumping through these hoops was I able to turn on or off pretty printing based on my ${json.prettyPrint} value (that is set as a property depending on how the app is deployed).

在跳过这些圈之后,我才能够根据我的${json打开或关闭漂亮的打印。prettyPrint}值(根据应用程序的部署方式设置为属性)。

I hope this helps someone out in the future!

我希望这对未来的人有所帮助!

#3


23  

When you are using Jackson 2.0.0, you can do it in a way Les wanted to. I currently use RC3 and the configuration seems to be working as expected.

当你使用Jackson 2.0.0时,你可以用Les想要的方式来做。我目前使用的是RC3,配置似乎与预期的一样。

ObjectMapper jacksonMapper = new ObjectMapper();
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

translates

翻译

{"foo":"foo","bar":{"field1":"field1","field2":"field2"}}

into

{
  "foo" : "foo",
  "bar" : {
    "field1" : "field1",
    "field2" : "field2"
  }
}

#4


22  

How do I make Jackson pretty-print the JSON content it generates?

如何使Jackson漂亮地打印它生成的JSON内容?

Here's a simple example:

这是一个简单的例子:

Original JSON Input:

原始JSON输入:

{"one":"AAA","two":["BBB","CCC"],"three":{"four":"DDD","five":["EEE","FFF"]}}

Foo.java:

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;}
}

Output:

输出:

{
  "one" : "AAA",
  "two" : [ "BBB", "CCC" ],
  "three" : {
    "four" : "DDD",
    "five" : [ "EEE", "FFF" ]
  }
}

If this approach doesn't exactly fit your needs, if you search the API docs v1.8.1 for "pretty", it'll turn up the relevant components available. If you use API version 2.x then look instead at the newer API 2.1.0 docs.

如果这个方法不能完全满足您的需求,如果您搜索API文档v1.8.1以获得“漂亮”,它将会找到可用的相关组件。如果您使用的是API版本2。然后看看更新的API 2.1.0文档。

#5


22  

Might I suggest this approach, it is valid with Spring 4.0.x and possibly older versions.

我建议这个方法,它在Spring 4.0中是有效的。可能是旧版本。

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());
    }

}

Thanks to Willie Wheeler for the solution: Willie Wheeler's Spring blog

感谢威利·惠勒的解决方案:威利·惠勒的Spring博客

#6


6  

Pretty print will be enable by adding and configure the MappingJackson2HttpMessageConverter converter. Disable prettyprint within production environment.

通过添加和配置MappingJackson2HttpMessageConverter转换器,将启用漂亮的打印。在生产环境中禁用prettyprint。

Message converter configuration

消息转换器配置

<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>

#7


4  

Based on baeldung this could be a nice idea using java 8:

基于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);
    }
}

#8


3  

I had trouble getting the custom MappingJacksonHttpMessageConverter to work as suggested above but I was finally able to get it to work after struggling w/ the configuration. From the code stand point I did exactly what was mentioned above but I had to add the following configuration to my springapp-servlet.xml to get it to work.

我很难让自定义的MappingJacksonHttpMessageConverter能够像上面建议的那样工作,但是我终于能够让它在w/配置工作困难之后继续工作。从代码的角度来看,我确实做到了上面提到的内容,但是我不得不将下面的配置添加到springappservlet中。xml让它工作。

I hope this helps others who are looking to implement the same.

我希望这能帮助其他希望实现相同功能的人。

<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>

#9


3  

Jackson 2 has a nicer API, agreed, but it won't resolve this problem in a Spring MVC environment given Spring MVC uses ObjectMapper#writeValue(JsonGenerator, Object) to write objects out as JSON. This writeValue variant does not apply ObjectMapper serialization features such as INDENT_OUTPUT in either Jackson 1.x or 2.0.

Jackson 2有一个更好的API,同意这一点,但是在Spring MVC使用ObjectMapper#writeValue(JsonGenerator, Object)将对象写为JSON的情况下,它不能在Spring MVC环境中解决这个问题。这个writeValue变体不应用ObjectMapper序列化特性,比如Jackson 1中的INDENT_OUTPUT。x或2.0。

I do think this is somewhat confusing. Since we use the ObjectMapper to construct JsonGenerators, I'd expect returned generators to be initialized based on configured ObjectMapper settings. I reported this as a issue against Jackson 2.0 here: https://github.com/FasterXML/jackson-databind/issues/12.

我认为这有点令人困惑。由于我们使用ObjectMapper来构造jsongenerator,我希望返回的生成器能够根据配置的ObjectMapper设置进行初始化。我在这里报告了Jackson 2.0的一个问题:https://github.com/FasterXML/jackson-databind/issues/12。

Les's suggestion of calling JsonGenerator#useDefaultPrettyPrinter based on the value of a prettyPrint flag is about the best we can do at the moment. I've gone ahead and created a Jackson2 HttpMessageConverter that does this based on the enabled status of the INDENT_OUTPUT SerializationFeature: https://gist.github.com/2423129.

Les关于基于prettyPrint标志的值调用JsonGenerator#useDefaultPrettyPrinter的建议是我们目前所能做的最好的。我已经创建了一个Jackson2 HttpMessageConverter,它基于INDENT_OUTPUT SerializationFeature的启用状态:https://gist.github.com/2423129。

#10


1  

I would make that a rendering issue, not the concern of the REST service.

我认为这是一个呈现问题,而不是REST服务关心的问题。

Who's doing the rendering? Let that component format the JSON. Maybe it can be two URLs - one for production and another for development.

做渲染的是谁?让该组件格式化JSON。可能有两个url——一个用于生产,另一个用于开发。

#1


36  

If you are using Spring Boot 1.2 or later the simple solution is to add

如果您正在使用Spring Boot 1.2或更高版本,简单的解决方案是添加

spring.jackson.serialization.INDENT_OUTPUT=true

to the application.properties file. This assumes that you are using Jackson for serialization.

给应用程序。属性文件。这假定您正在使用Jackson进行序列化。

If you are using an earlier version of Spring Boot then you can add

如果您使用的是较早版本的Spring Boot,那么您可以添加。

http.mappers.json-pretty-print=true

This solution still works with Spring Boot 1.2 but it is deprecated and will eventually be removed entirely. You will get a deprecation warning in the log at startup time.

这个解决方案仍然适用于Spring Boot 1.2,但它已被弃用,最终将被完全删除。在启动时,您将在日志中获得一个弃用警告。

(tested using spring-boot-starter-web)

(使用spring-boot-starter-web测试)

#2


31  

I had an answer when I posted this question, but I thought I'd post it anyway in case there are better alternative solutions. Here was my experience:

当我发布这个问题的时候,我得到了一个答案,但是我想我还是要发布它,以防有更好的替代解决方案。这是我的经验:

First thing's first. The MappingJacksonHttpMessageConverter expects you to inject a Jackson ObjectMapper instance and perform Jackson configuration on that instance (and not through a Spring class).

第一件事是第一次。MappingJacksonHttpMessageConverter期望您注入一个Jackson ObjectMapper实例并在该实例上执行Jackson配置(而不是通过Spring类)。

I thought it would be as easy as doing this:

我觉得这样做很简单:

Create an ObjectMapperFactoryBean implementation that allows me to customize the ObjectMapper instance that can be injected into the MappingJacksonHttpMessageConverter. For example:

创建一个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>

And then, in my ObjectMapperFactoryBean implementation, I could do this (as has been documented as a solution elsewhere on SO):

然后,在我的ObjectMapperFactoryBean实现中,我可以这样做(正如其他地方的解决方案所记录的那样):

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, isPrettyPrint());
return mapper;

But it didn't work. And trying to figure out why is a nightmare. It is a major test of patience to figure Jackson out. Looking at its source code only confuses you further as it uses outdated and obtuse forms of configuration (integer bitmasks for turning on/off features? Are you kidding me?)

但它不工作。试图弄明白为什么这是一场噩梦。这是对杰克逊耐心的一次重大考验。查看它的源代码只会让您更加困惑,因为它使用过时的、迟钝的配置形式(用于打开/关闭特性的整数位掩码?)你在跟我开玩笑吧?)

I essentially had to re-write Spring's MappingJacksonHttpMessageConverter from scratch, and override its writeInternal implementation to be the following:

实际上,我必须从头重写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);
    }
}

The only thing I added to the existing implementation is the following block:

我在现有的实现中添加的唯一内容是:

if (isPrettyPrint()) {
    jsonGenerator.useDefaultPrettyPrinter();
}

isPrettyPrint() is just a JavaBeans compatible getter w/ matching setter that I added to my MappingJacksonHttpMessageConverter subclass.

isPrettyPrint()只是我添加到MappingJacksonHttpMessageConverter子类的一个javabean兼容的getter /匹配setter。

Only after jumping through these hoops was I able to turn on or off pretty printing based on my ${json.prettyPrint} value (that is set as a property depending on how the app is deployed).

在跳过这些圈之后,我才能够根据我的${json打开或关闭漂亮的打印。prettyPrint}值(根据应用程序的部署方式设置为属性)。

I hope this helps someone out in the future!

我希望这对未来的人有所帮助!

#3


23  

When you are using Jackson 2.0.0, you can do it in a way Les wanted to. I currently use RC3 and the configuration seems to be working as expected.

当你使用Jackson 2.0.0时,你可以用Les想要的方式来做。我目前使用的是RC3,配置似乎与预期的一样。

ObjectMapper jacksonMapper = new ObjectMapper();
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

translates

翻译

{"foo":"foo","bar":{"field1":"field1","field2":"field2"}}

into

{
  "foo" : "foo",
  "bar" : {
    "field1" : "field1",
    "field2" : "field2"
  }
}

#4


22  

How do I make Jackson pretty-print the JSON content it generates?

如何使Jackson漂亮地打印它生成的JSON内容?

Here's a simple example:

这是一个简单的例子:

Original JSON Input:

原始JSON输入:

{"one":"AAA","two":["BBB","CCC"],"three":{"four":"DDD","five":["EEE","FFF"]}}

Foo.java:

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;}
}

Output:

输出:

{
  "one" : "AAA",
  "two" : [ "BBB", "CCC" ],
  "three" : {
    "four" : "DDD",
    "five" : [ "EEE", "FFF" ]
  }
}

If this approach doesn't exactly fit your needs, if you search the API docs v1.8.1 for "pretty", it'll turn up the relevant components available. If you use API version 2.x then look instead at the newer API 2.1.0 docs.

如果这个方法不能完全满足您的需求,如果您搜索API文档v1.8.1以获得“漂亮”,它将会找到可用的相关组件。如果您使用的是API版本2。然后看看更新的API 2.1.0文档。

#5


22  

Might I suggest this approach, it is valid with Spring 4.0.x and possibly older versions.

我建议这个方法,它在Spring 4.0中是有效的。可能是旧版本。

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());
    }

}

Thanks to Willie Wheeler for the solution: Willie Wheeler's Spring blog

感谢威利·惠勒的解决方案:威利·惠勒的Spring博客

#6


6  

Pretty print will be enable by adding and configure the MappingJackson2HttpMessageConverter converter. Disable prettyprint within production environment.

通过添加和配置MappingJackson2HttpMessageConverter转换器,将启用漂亮的打印。在生产环境中禁用prettyprint。

Message converter configuration

消息转换器配置

<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>

#7


4  

Based on baeldung this could be a nice idea using java 8:

基于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);
    }
}

#8


3  

I had trouble getting the custom MappingJacksonHttpMessageConverter to work as suggested above but I was finally able to get it to work after struggling w/ the configuration. From the code stand point I did exactly what was mentioned above but I had to add the following configuration to my springapp-servlet.xml to get it to work.

我很难让自定义的MappingJacksonHttpMessageConverter能够像上面建议的那样工作,但是我终于能够让它在w/配置工作困难之后继续工作。从代码的角度来看,我确实做到了上面提到的内容,但是我不得不将下面的配置添加到springappservlet中。xml让它工作。

I hope this helps others who are looking to implement the same.

我希望这能帮助其他希望实现相同功能的人。

<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>

#9


3  

Jackson 2 has a nicer API, agreed, but it won't resolve this problem in a Spring MVC environment given Spring MVC uses ObjectMapper#writeValue(JsonGenerator, Object) to write objects out as JSON. This writeValue variant does not apply ObjectMapper serialization features such as INDENT_OUTPUT in either Jackson 1.x or 2.0.

Jackson 2有一个更好的API,同意这一点,但是在Spring MVC使用ObjectMapper#writeValue(JsonGenerator, Object)将对象写为JSON的情况下,它不能在Spring MVC环境中解决这个问题。这个writeValue变体不应用ObjectMapper序列化特性,比如Jackson 1中的INDENT_OUTPUT。x或2.0。

I do think this is somewhat confusing. Since we use the ObjectMapper to construct JsonGenerators, I'd expect returned generators to be initialized based on configured ObjectMapper settings. I reported this as a issue against Jackson 2.0 here: https://github.com/FasterXML/jackson-databind/issues/12.

我认为这有点令人困惑。由于我们使用ObjectMapper来构造jsongenerator,我希望返回的生成器能够根据配置的ObjectMapper设置进行初始化。我在这里报告了Jackson 2.0的一个问题:https://github.com/FasterXML/jackson-databind/issues/12。

Les's suggestion of calling JsonGenerator#useDefaultPrettyPrinter based on the value of a prettyPrint flag is about the best we can do at the moment. I've gone ahead and created a Jackson2 HttpMessageConverter that does this based on the enabled status of the INDENT_OUTPUT SerializationFeature: https://gist.github.com/2423129.

Les关于基于prettyPrint标志的值调用JsonGenerator#useDefaultPrettyPrinter的建议是我们目前所能做的最好的。我已经创建了一个Jackson2 HttpMessageConverter,它基于INDENT_OUTPUT SerializationFeature的启用状态:https://gist.github.com/2423129。

#10


1  

I would make that a rendering issue, not the concern of the REST service.

我认为这是一个呈现问题,而不是REST服务关心的问题。

Who's doing the rendering? Let that component format the JSON. Maybe it can be two URLs - one for production and another for development.

做渲染的是谁?让该组件格式化JSON。可能有两个url——一个用于生产,另一个用于开发。