Spring mvc: изменение формата ответа по умолчанию от xml до json

Я прошел через другие подобные вопросы, но ничего не работало для меня.

Все мои API возвращают JSON как ответ по умолчанию:

Из-за некоторого XML API мне пришлось добавить jackson-xml

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

Теперь по умолчанию " Без заголовка принятия" Все ответы XML.

Я хотел бы иметь JSON в качестве формата ответа по умолчанию.

Как указано в документе:

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

Я реализовал следующую конфигурацию:

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

Случай 1:, если я создаю ignoreAcceptHeader(true), тогда все JSON даже XML API возвращает JSON.

Случай 2:, когда ignoreAcceptHeader(false), по умолчанию, является XML.

Я забыл упомянуть, что мой API выглядит так:

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

Я совсем потерялся здесь. Все, что я хочу, это Default (Without AcceptHeader), должен быть JSON. (API возвращает XML как String)

И когда Accept Header: "Application/xml" определен, тогда ответ должен быть XML.

Любой совет будет очень полезен.

Спасибо.

Ответ 1

В общем, если вы хотите получить ответ json, вам нужен модуль jackson-databind:

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

а затем вы должны определить MappingJackson2HttpMessageConverter в своей конфигурации:

@Configuration
@EnableWebMvc
public class WebAppMainConfiguration extends WebMvcConfigurerAdapter {

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

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

    [...]
}

В вашем случае вы можете реализовать свой собственный AbstractGenericHttpMessageConverter, чтобы вы могли включить этот конвертер между различными бетонными преобразователями в зависимости от типа носителя.

Проверьте метод AbstractGenericHttpMessageConverter#writeInternal(..)

Ответ 2

Поскольку вы установили ignoreAcceptHeader в true, а favourPathExtension в false, Spring будет полагаться на другие альтернативы для согласования содержимого. Значит будет выглядеть параметр URL, который вы настроили XML и JSON

так как @stan указал /getXml?mediaType=xml будет возвращать ответ XML, иначе он будет по умолчанию json(defaultContentType(MediaType.APPLICATION_JSON))

Ответ 3

Для меня добавление

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

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

}

решил проблему.

Теперь по умолчанию все RestController возвращают JSON, если в запросе нет заголовка Accept. Также, если передается заголовок Accept: application/xml, то результатом является XML.

Также стоит прочитать: https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc