19

I have gone through other similar asked questions but nothing worked for me.

All my API's return JSON as response by Default:

Because of some XML API, i had to add jackson-xml

    <dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

Now by default "Without accept header" All responses are XML.

I would like to have JSON as default Response format .

As stated in the doc here:

https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

I implemented the following config :

@Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true)    
                .useJaf(false).defaultContentType(MediaType.APPLICATION_JSON)
                .mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
    }

Case 1: if i make the ignoreAcceptHeader(true) then everything is JSON even the XML API returning JSON.

Case 2: when ignoreAcceptHeader(false) is then default is XML.

I forget to mention my API's look like this:

@RequestMapping(value = "/getXml", method = RequestMethod.GET)
public ResponseEntity<String> getXml( HttpServletRequest request)
        throws JAXBException {
    return returnXml();
}

I am quite lost here, All i want is Default(Without AcceptHeader) should be JSON. (API returns XML as String)

And when Accept Header : "Application/xml" is defined then response should be XML.

Any advice would be of great help.

Thanks.

lesnar
  • 2,400
  • 7
  • 41
  • 72
  • 2
    According to configuration you can control return media type with 'mediaType' parameter. Did you try something like /getXml?mediaType=xml – Stan Dec 08 '16 at 10:05
  • @Stan : no i cannot change the RequestMapping but still i will try it to see the results – lesnar Dec 08 '16 at 10:06
  • 1
    It's not about request mapping annotation, as I understood you are saying to Spring with .parameterName("mediaType") statement to check media type using this parameter so there are no changes on your server side – Stan Dec 08 '16 at 10:08
  • @Stan : it worked :) :) but then i have to communicate new URL to customer? or i can manipulate the URL once i recieve the request ? – lesnar Dec 08 '16 at 10:11
  • @Stan : if i am not wrong, then adding something like response.setContentType(MediaType.APPLICATION_XML_VALUE); in API would be same right ? – lesnar Dec 08 '16 at 10:12
  • Not sure it will be the same since haven't seen how Spring handles that. Another option if you have fixed endpoints for XML you can probably add "produces" attribute to RequestMapping annotation. – Stan Dec 08 '16 at 10:19

3 Answers3

7

In general if you want to get json response you need an jackson-databind module:

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>${json-jackson-version}</version> 
</dependency> 

and then you have to define a MappingJackson2HttpMessageConverter in your configuration:

@Configuration
@EnableWebMvc
public class WebAppMainConfiguration extends WebMvcConfigurerAdapter {

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
        converters.add(new MappingJackson2HttpMessageConverter());

        [..] 
        super.configureMessageConverters(converters); 
    }

    [...]
}

In your case, you can implement your own AbstractGenericHttpMessageConverter so you can switch in this converter between different concrete converters depending on media type.

Check the method AbstractGenericHttpMessageConverter#writeInternal(..)

alex
  • 8,904
  • 6
  • 49
  • 75
7

For me, adding

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
    }

}

solved the problem.

Now by default all RestControllers return JSON, if no Accept header in the request. Also if Accept: application/xml header is passed, then result is XML.

Also, worth reading: https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

Ruslan Stelmachenko
  • 4,987
  • 2
  • 36
  • 51
  • 1
    Just a detail: in a Spring boot application, your `@Configuration` classes should not contain the `@EnableWebMvc` annotation ([source](https://dzone.com/articles/spring-boot-enablewebmvc-and-common-use-cases)). It may prevent other things from working, such as the springfox-swagger-ui html page. – Paulo Merson Jun 05 '18 at 20:23
  • 1
    @PauloMerson Yes, you are totally right! I'll remove this from the answer to prevent confuse any readers, thanks! – Ruslan Stelmachenko Jun 05 '18 at 22:50
2

As you have set ignoreAcceptHeader to true and favorPathExtension to false, spring will rely on other alternatives for content negotiations. Means it will look URL parameter which you have configured XML and JSON

so as @stan pointed /getXml?mediaType=xml will should return xml response else it will default to json(defaultContentType(MediaType.APPLICATION_JSON))

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
kuhajeyan
  • 10,727
  • 10
  • 46
  • 71
  • thanks for your response, but i am already doing something like this : contentTypeList.add(MediaType.APPLICATION_XML_VALUE); headers.put("Content-Type", contentTypeList); and i expect it to send XML without "?mediatype=xml" – lesnar Dec 08 '16 at 10:35
  • but this is not happening. – lesnar Dec 08 '16 at 10:38