2015-05-13 15 views
6

Mam kontroler wiosny MVC z następującą metodą:wiosna MVC powrót restcontroller json ciąg

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

To siedzi wewnątrz kontrolera, który rozpoczyna się tak:

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

Kiedy dzwonić do innych metod, które zwracaj obiekty, te obiekty są serializowane przez Jacksona do JSON. Ale ta metoda, która zwraca ciąg, nie jest konwertowana na JSON. W przypadku, gdy nie jest jasne, oto przykład za pomocą curl:

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

Tak więc problem jest to, że „test” bez cudzysłowów nie jest ciągiem JSON, ale mój klient REST spodziewa się łańcuch. Spodziewałem polecenia curl, aby pokazać, że ciąg z cudzysłowy wokół niego, dlatego zamiast JSON prawny:

"test" 

Używam Wiosna WebMVC 4.1.3 oraz 2.4.3 Jacksona. Próbowałem dodać atrybut "produkuje" do RequestMapping, aby powiedzieć, że powinien zwrócić JSON. W takim przypadku atrybut Content-Type odesłany to "application/json", ale nadal ciąg testowy nie jest cytowany.

Mogę obejść to, dzwoniąc do biblioteki JSON, aby przekonwertować przez Java String do JSON, ale wygląda na to, że Spring MVC i Jackson zazwyczaj robią to automatycznie. Jednak jakoś nie robią tego w moim przypadku. Jakieś pomysły, które źle skonfigurowałem, aby otrzymać test zamiast "testu"?

+0

Możesz spróbować owinąć swój ciąg w obiekt. W przeciwnym razie Jackson nie będzie wiedział, jaką nazwę nadać kluczowi JSON w twoim Łańcuchu. – Matt

+0

@Matt sam łańcuch jest prawidłowy JSON, nie musi być obiektem. Na przykład nawet tablica działa poprawnie. Jeśli zmienię kod, aby zwrócić tablicę, otrzymam '[" test "]'. Tak więc spodziewam się, że jeśli zwrócę prosty ciąg, powinienem dostać '" test "' –

+0

To nie jest takie oczywiste, spójrz na tę odpowiedź: http://stackoverflow.com/a/7487892/369946. Zgodnie z definicją RFC typu "application/json", JSON powinien być obiektem lub tablicą. – Matt

Odpowiedz

7

Okazuje się, że podczas korzystania z @EnableWebMvc adnotację, że zamienia na pęczek konwerterów wiadomości http domyślnie. Drugim na liście jest StringHttpMessageConverter, który według dokumentacji będzie stosowany dla typów zawartości text/*. Jednak po przejściu przez debugger, dotyczy obiektów String dla typów zawartości */* - co oczywiście obejmuje application/json.

Numer MappingJackson2HttpMessageConverter odpowiedzialny za typy zawartości znajduje się poniżej tej listy. Tak więc dla obiektów Java innych niż String, ten zostaje wywołany. Dlatego działał na typy Object i Array, ale nie na String - pomimo dobrych sugestii użycia atrybutu generate do ustawienia typu zawartości: application/json. Mimo że ten typ zawartości jest konieczny do uruchomienia tego konwertera, konwerter String najpierw chwytał to zadanie!

Jak już rozszerzenie klasy WebMvcConfigurationSupport dla innej konfiguracji, ja overrode następującą metodę, aby umieścić konwerter Jackson pierwszy więc kiedy Content-Type jest application/json następnie ten będzie używany zamiast konwertera String:

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

Teraz, gdy wywołuję metodę testową z loków, otrzymuję pożądane wyjście "test" zamiast tylko test, więc klient kątowy, który oczekuje JSON, jest teraz szczęśliwy.

0

Spróbuj coś takiego

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

Dzięki Martin, próbowałem, że produkuje atrybut, ale jak już wspomniałem, wszystko, co wydaje się zrobić, to zmienić Content-Type na "application/json", ale nadal wyjście jest 'test' bez cytatów. I @ResponseBody nie jest konieczne, ponieważ mam adnotację @RestController, która czyni to automatycznie. Mimo wszystko, wycinam i tworzę sugestię na wypadek, gdybym się mylił, ale bez powodzenia. –

1

Spróbuj tego:

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

Dzięki Shyam, próbowałem tego, ale po prostu ustawia Content-Type na "application/json", ale nie zawija mojego ciągu w cudzysłowie. Próbowałem wyciąć i wkleić twoją sugestię na wypadek, gdybym ją wpisał źle, ale to nie działa. –