2015-05-13 7 views
6

У меня есть контроллер Spring MVC с помощью следующего метода:Spring MVC возвращение restcontroller JSON строку

@RequestMapping(value = "/stringtest", method = RequestMethod.GET) 
public String simpletest() throws Exception { 
    return "test"; 
} 

Это сидит внутри контроллера, который начинается так:

@RestController 
@RequestMapping(value = "/root") 
public class RootController 

Когда я звоню другие методы, возвращают объекты, эти объекты сериализуются Джексоном в JSON. Но этот метод, который возвращает строку, не преобразуется в JSON. В случае, если это не ясно, вот пример использования завитка:

$curl http://localhost:8080/clapi/root/stringtest 
test 

Таким образом, проблема в том, что «тест» без кавычек не является строка JSON, но мой REST клиент ожидает строку. Я ожидал, что завиток команду, чтобы показать эту строку в кавычки вокруг него, так что это законно JSON вместо:

"test" 

Я использую Spring WebMVC 4.1.3 и 2.4.3 Джексона. Я попытался добавить атрибут «производит» в RequestMapping, чтобы сказать, что он должен возвращать JSON. В этом случае атрибут Content-Type, отправленный обратно, является «application/json», но тестовая строка не цитируется.

Я мог бы обойти это, вызвав библиотеку JSON для преобразования Java String в JSON, но, похоже, Spring MVC и Jackson обычно делают это автоматически. Но почему-то они не делают этого в моем случае. Любые идеи, что я, возможно, неправильно настроил, чтобы просто проверить тест вместо «теста»?

+0

Вы можете попробовать обернуть свою строку в объект. В противном случае Джексону не удастся узнать, какое имя следует присвоить ключу JSON вашей строки. – Matt

+0

@Matt только одна строка действительна JSON, она не обязательно должна быть объектом. Например, даже массив работает отлично. Если я изменил код для возврата массива, я получаю '[" test "]'. Поэтому я ожидаю, что если я верну простую строку, я должен получить '' test "' –

+0

Это не так очевидно, посмотрите на этот ответ: http://stackoverflow.com/a/7487892/369946. Согласно RFC-определению типа «application/json», JSON должен быть объектом или массивом. – Matt

ответ

7

Оказывается, что при использовании @EnableWebMvc аннотацию, что она превращается в кучу конвертеров HTTP сообщений по умолчанию. Второй в списке - StringHttpMessageConverter, о котором говорится в документации, для типов контента text/*. Однако после перехода с помощью отладчика он применяется к объектам String для типов контента */*, который, очевидно, включает в себя application/json.

MappingJackson2HttpMessageConverter, который отвечает за типы контента application/json, включен в этот список. Поэтому для объектов Java, отличных от String, этот вызов вызывается. Вот почему он работал для типов Object и Array, но не String - несмотря на хорошие рекомендации по использованию атрибута generate для установки типа содержимого application/json. Хотя этот тип контента необходим для запуска этого конвертера, преобразователь String захватывал работу первым!

Как я расширение WebMvcConfigurationSupport класса для какой-либо другой конфигурации, я переопределил следующий метод, чтобы поместить преобразователь Джексона сначала так, когда содержание-тип application/json, этот один будет использоваться вместо преобразователя струнного:

@Override 
protected void configureMessageConverters(
     List<HttpMessageConverter<?>> converters) { 
    // put the jackson converter to the front of the list so that application/json content-type strings will be treated as JSON 
    converters.add(new MappingJackson2HttpMessageConverter()); 
    // and probably needs a string converter too for text/plain content-type strings to be properly handled 
    converters.add(new StringHttpMessageConverter()); 
} 

Теперь, когда я вызываю метод проверки из curl, я получаю желаемый вывод "test" вместо test, поэтому теперь мы рады видеть, что угловой клиент, ожидающий JSON, счастлив.

0

Try что-то вроде этого

@RequestMapping(value = "/stringtest", method = RequestMethod.GET, produces="application/json") 
public @ResponseBody String simpletest() throws Exception { 
    return "test"; 
} 
+0

Спасибо, Martin, я пробовал это, создавая атрибут, но, как я уже сказал, все, что кажется, это изменить Content-Type на «application/json», но все же вывод «test» без кавычек. И @ResponseBody не требуется, потому что у меня есть аннотация @RestController, которая делает это автоматически. Тем не менее, я отказываюсь от вашего предложения на случай, если я ошибаюсь в этом, но не повезло. –

1

Попробуйте это:

@RequestMapping(value = "/stringtest", method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE) 
+0

Спасибо Shyam, я пробовал это, но он просто устанавливает Content-Type в «application/json», но не переносит мою строку в кавычки. Я попытался вырезать и вставить ваше предложение, если я набрал его неправильно, но он не работает. –

Смежные вопросы