2014-05-10 11 views
10

Diamo un'occhiata al seguente controller semplice test (usato con Primavera 4.0.3):stringa Semplice come JSON valore di ritorno nel controller di primavera resto

@RestController 
public class TestController 
{ 
    @RequestMapping("/getList") 
    public List<String> getList() 
    { 
     final List<String> list = new ArrayList<>(); 
     list.add("1"); 
     list.add("2"); 
     return list; 
    } 

    @RequestMapping("/getString") 
    public String getString() 
    { 
     return "Hello World"; 
    } 
} 

In teoria entrambi i metodi del controller dovrebbe tornare JSON valido. Chiamando il primo metodo di controllo effettivamente restituire il seguente array JSON:

$ curl -i -H "Accept: application/json" http://localhost:8080/getList 
HTTP/1.1 200 OK 
Content-Type: application/json;charset=UTF-8 

["1","2"] 

Ma il secondo metodo di controllo restituisce la stringa senza virgolette, che non è una stringa JSON valida:

$ curl -i -H "Accept: application/json" http://localhost:8080/getString 
HTTP/1.1 200 OK 
Content-Type: application/json;charset=UTF-8 

Hello World 

Perché è così? Può essere configurato? E 'un errore? O una caratteristica che non capisco?

+1

Cerca in 'StringHttpMessageConverter' quale è stato registrato prima del convertitore di jackson. –

risposta

8

Quando si restituisce un oggetto String, Spring MVC lo interpreta come contenuto da inserire nel corpo della risposta e non lo modifica ulteriormente. Se si desidera che una stringa effettiva sia la risposta JSON, è necessario specificarla manualmente o eseguirla esplicitamente tramite Jackson.

+0

Mi sembra abbastanza strano. Secondo l'intestazione 'Accept' nella richiesta l'unica risposta valida deve essere di tipo contenuto' application/json' quindi Spring deve usare Jackson per la risposta e Jackson dovrebbe produrre JSON valido. In questo caso la risposta è semplicemente non valida. Ha il tipo di contenuto 'application/json' ma non è stato convertito in JSON. – kayahr

+3

@kayahr Ma se si volesse produrre la propria stringa JSON senza Jackson (forse una concatenazione di stringhe molto semplice)? Quindi Spring dovrebbe ri-analizzare la tua risposta solo per controllarti. 'ResponseBody' significa' ResponseBody', che in definitiva è una sequenza di byte, e Spring esegue solo le conversioni se non può eguagliare i tipi Java in questione; 'String' non ha bisogno di conversione. – chrylis

2

È possibile rimuovere il che è registrato prima del convertitore di jackson, - come menzionato nel commento.

/** 
* Unregister the default {@link StringHttpMessageConverter} as we want 
* Strings to be handled by the JSON converter. 
* 
* Our MappingJackson2HttpMessageConverter will deal with strings. 
* 
* @param converters 
*   List of already configured converters 
*/ 
@Override 
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { 

    Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); 

    while (iterator.hasNext()) { 
     HttpMessageConverter<?> converter = iterator.next(); 

     if (converter instanceof StringHttpMessageConverter) { 
      iterator.remove(); 
     } 
    } 
} 
+0

Bella soluzione, funziona bene. –

0

Se si desidera restituire un oggetto String, Spring MVC interpreta che come il contenuto di mettere nel corpo di risposta e non modifica ulteriormente. Se si desidera che una stringa effettiva sia la risposta JSON, è necessario specificarla manualmente o eseguirla esplicitamente tramite Jackson.

@RestController 
public class TestController 
{ 
    @RequestMapping("/getString") 
    public String getString() 
    { 
    return JSONObject.quote("Hello World"); 
    } 
} 
0

qui sono i passi che ho fatto per raggiungere questo obiettivo:

  1. Aggiungi dipendenza nel file di pom:

    <dependency> 
        <groupId>com.fasterxml.jackson.core</groupId> 
        <artifactId>jackson-databind</artifactId> 
        <version>2.9.3</version> 
    </dependency> 
    
  2. Mettere @ResponseBody annotazione sul vostro metodo come questo:

    @RequestMapping(value = "/getCountries", method = RequestMethod.GET)  
    @ResponseBody  
    public List<Country> getCountries() {  
        return countryDAO.list();  
    } 
    
Problemi correlati