9

I want to make sure that the JSON files generated by Jackson are never pretty print. I'm a junior working on a pre-existing project, so I need to work backwards to find out all the ways that JSON can be configured to output as pretty print. I can confirm there are 0 references to .defaultPrettyPrintingWriter() in the project, as well as 0 references to .setSerializationConfig, which I believe may also be used to enable pretty print.

So how else is this possible? Alternatively, is there a sure-fire way to ensure the JSON file is not pretty print?

tamuren
  • 1,072
  • 4
  • 15
  • 32
  • Are you using any beans or an application server? You might want to check for a `prettyPrint` property in the config files. – Jon Lin Aug 07 '12 at 18:47
  • UPDATE: I found several instances of ObjectMapper in the project I'm working on. If I wrote something like OutputMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, false); Then I'll get the non-pretty print JSON I'm looking for, right? – tamuren Aug 07 '12 at 18:47
  • *"OutputMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, false); Then I'll get the non-pretty print JSON I'm looking for, right?"** In theory, yes, that should make that instance of ObjectMapper not pretty print. There could still be other ways ObjectMappers get created though. – Jon Lin Aug 07 '12 at 18:50
  • EDIT: To elaborate, I searched the project for all new ObjectMapper objects, but I suppose if there was a way to create an ObjectMapper than simply "private static final ObjectMapper objectMapper;" then there may still be unaffacted ObjectMapper objects. – tamuren Aug 07 '12 at 19:37
  • Like if it's created through a factory and transparently gets used. Something like: `getMapperFactory().getMapper().getJsonFactory().createJsonGenerator(message);` You wouldn't be able to grep that because there's not an explicit instance variable for an `ObjectMapper`. But I don't know what this code looks like, so this may be moot – Jon Lin Aug 07 '12 at 19:38
  • I turned off the SerializationConfig feature INDENT_OUTPUT to false on all instances of ObjectMapper, but now the JSON responses are pretty print only some of the time. I believe that a factory may be in use as well, how can I track down where this is being used? – tamuren Aug 09 '12 at 14:58
  • Not really sure what would be best in your case, if you have services or things like beans, check the config, otherwise you'll have to just sift through the code I guess. – Jon Lin Aug 09 '12 at 19:39
  • Where can I find the config for Jackson? – tamuren Oct 23 '12 at 12:43

3 Answers3

2

Depending on what version of Spring you are using the MappingJacksonHttpMessageConverte‌​r should have a boolean property named prettyPrint to configure the printer when serializing JSON.

So this XML configuration should do the trick (if you are using a recent version of Spring 3)

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAda‌​pter">
  <property name="messageConverters">
    <list>
      <ref bean="jsonConverter" />
    </list>
  </property>
</bean>

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverte‌​r">
  <property name="supportedMediaTypes" value="application/json" />
  <property name="objectMapper" ref="jacksonObjectMapper" />
  <property name="prettyPrint" value="false" />
</bean>

You can see the related commit on github introducing the property. And the trunk version of the class too, that includes this property. Finally this is the Spring Jira issue SPR-7201 related to the previous commit.

Or you could try to update your version of Jackson to a more recent one that includes the useDefaultPrettyPrinter and setPrettyPrinter methods as mentioned by Alexander Ryzhov

Alex
  • 25,147
  • 6
  • 59
  • 55
1

The most elegant solution is to put the switch for pretty/non-pretty into a filter, and reuse static configuration objects. This prevents useless garbage collections.

/**
 * Evaluate the "pretty" query parameter. If given without any value, or with "true": pretty JSON output.
 * E.g. /test?pretty or /test?pretty=true
 * Otherwise output without any formatting.
 *
 * @see https://stackoverflow.com/questions/10532217/jax-rs-json-pretty-output
 */
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class RestPrettyJsonFilter implements ContainerResponseFilter {

  public static final String QUERYPARAM_PRETTY = "pretty";

  private static final IndentingModifier INDENTING_MODIFIER_PRETTY = new IndentingModifier(true);
  private static final IndentingModifier INDENTING_MODIFIER_NOT_PRETTY = new IndentingModifier(false);

  @Override
  public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException {

    boolean pretty = false;

    UriInfo uriInfo = reqCtx.getUriInfo();
    //log.info("prettyFilter: "+uriInfo.getPath());

    MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
    if(queryParameters.containsKey(QUERYPARAM_PRETTY)) {
      // Pretty query parameter is present
      String prettyParam = queryParameters.getFirst(QUERYPARAM_PRETTY);

      // Pretty is present without any value, or value is set to "true"?
      if (prettyParam == null || "".equals(prettyParam) || "true".equals(prettyParam)) {
        pretty = true;
      }
    }

    // Prevent recreation of objects over and over again
    //ObjectWriterInjector.set(new IndentingModifier(pretty));
    if (pretty) {
      ObjectWriterInjector.set(INDENTING_MODIFIER_PRETTY);
    } else {
      ObjectWriterInjector.set(INDENTING_MODIFIER_NOT_PRETTY);
    }
  }

  /**
   * Used to switch on / off pretty output for each response.
   */
  public static class IndentingModifier extends ObjectWriterModifier {

    private final boolean indent;

    /** Minimal pretty printer is not printing pretty. */
    private final static PrettyPrinter NOT_PRETTY_PRINTER = new com.fasterxml.jackson.core.util.MinimalPrettyPrinter();

    public IndentingModifier(boolean indent) {
      this.indent = indent;
    }

    /* (non-Javadoc)
     * @see com.fasterxml.jackson.jaxrs.cfg.ObjectWriterModifier#modify(com.fasterxml.jackson.jaxrs.cfg.EndpointConfigBase, javax.ws.rs.core.MultivaluedMap, java.lang.Object, com.fasterxml.jackson.databind.ObjectWriter, com.fasterxml.jackson.core.JsonGenerator)
     */
    @Override
    public ObjectWriter modify(EndpointConfigBase<?> endpointConfigBase, MultivaluedMap<String, Object> multivaluedMap, Object o, ObjectWriter objectWriter, JsonGenerator jsonGenerator) throws IOException {
      if(indent) {
        // Pretty
        jsonGenerator.useDefaultPrettyPrinter();
      } else {
        // Not pretty
        jsonGenerator.setPrettyPrinter(NOT_PRETTY_PRINTER);
      }
      return objectWriter;
    }
  }
}
0

Not sure which version of Jackson you are using but in the latest version (1.9.10), the default behavior of JsonGenerator is no pretty print. The easiest way to turn it on is to call generator.useDefaultPrettyPrinter() or generator.setPrettyPrinter(new DefaultPrettyPrinter()). Try searching for useDefaultPrettyPrinter and setPrettyPrinter and remove those statements.

Alexander Ryzhov
  • 2,705
  • 3
  • 19
  • 19
  • The version this project is using is 1.3. I searched the project for useDefaultPrettyPrinter and setPrettyPrinter, to no avail – tamuren Oct 25 '12 at 13:04