2013-03-22 11 views
7

Sto sviluppando e l'applicazione Android che comunica con il mio server. Questa comunicazione è fatta attraverso Spring framework e Jackson. Sto inviando una richiesta per il mio server con successo ma non ricevo la risposta. Ecco quello che ho fatto:HttpMessageNotReadableException: Impossibile leggere JSON: campo non riconosciuto utilizzando Spring per Android

Android:

public Loja getLoja() { 
     RestTemplate restTemplate = new RestTemplate(); 
     restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter()); 
     restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); 

     String url = BASE_URL + "/android/played.json"; 
     return restTemplate.getForObject(url, Loja.class); 
    } 

classe Loja (ho due versioni di esso Uno su Android e altri in Server Essi sono completamente lo stesso..):

public class Loja { 

    private String nome; 
    private String xValue; 
    private String yValue; 
    private String andar; 

    public Loja(String nome, String xValue, String yValue, String andar) { 
     this.nome = nome; 
     this.xValue = xValue; 
     this.yValue = yValue; 
     this.andar = andar; 
    } 

    public Loja() { 
    } 

    public String getAndar() { 
     return andar; 
    } 

    public void setAndar(String andar) { 
     this.andar = andar; 
    } 

    public String getNome() { 
     return nome; 
    } 

    public void setNome(String nome) { 
     this.nome = nome; 
    } 

    public String getxValue() { 
     return xValue; 
    } 

    public void setxValue(String xValue) { 
     this.xValue = xValue; 
    } 

    public String getyValue() { 
     return yValue; 
    } 

    public void setyValue(String yValue) { 
     this.yValue = yValue; 
    } 

} 

Ed ecco il mio controller:

@RequestMapping("/android/played") 
    public ModelAndView getLoja() { 
     System.out.println("Android Resquest."); 

     Loja loja = new Loja("teste", "20", "30", "1"); 

     ModelAndView mav = new ModelAndView(); 
     mav.addObject("Loja", loja); 
     return mav; 
    } 

Con tutto questo sto ottenendo l'eccezione followin in Android :

03-21 22:13:06.197: E/AndroidRuntime(25342): java.lang.RuntimeException: An error occured while executing doInBackground() 
03-21 22:13:06.197: E/AndroidRuntime(25342): at android.os.AsyncTask$3.done(AsyncTask.java:299) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.lang.Thread.run(Thread.java:856) 
03-21 22:13:06.197: E/AndroidRuntime(25342): Caused by: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "Loja" (Class com.example.androidspring.Loja), not marked as ignorable 
03-21 22:13:06.197: E/AndroidRuntime(25342): at [Source: [email protected]; line: 1, column: 10] (through reference chain: com.example.androidspring.Loja["Loja"]); nested exception is org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "Loja" (Class com.example.androidspring.Loja), not marked as ignorable 
03-21 22:13:06.197: E/AndroidRuntime(25342): at [Source: [email protected]; line: 1, column: 10] (through reference chain: com.example.androidspring.Loja["Loja"]) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:125) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:147) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:76) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:484) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at com.example.androidspring.MainActivity.getLoja(MainActivity.java:59) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at com.example.androidspring.MainActivity$DownloadFilesTask.doInBackground(MainActivity.java:72) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at com.example.androidspring.MainActivity$DownloadFilesTask.doInBackground(MainActivity.java:1) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
03-21 22:13:06.197: E/AndroidRuntime(25342): ... 5 more 
03-21 22:13:06.197: E/AndroidRuntime(25342): Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "Loja" (Class com.example.androidspring.Loja), not marked as ignorable 
03-21 22:13:06.197: E/AndroidRuntime(25342): at [Source: [email protected]; line: 1, column: 10] (through reference chain: com.example.androidspring.Loja["Loja"]) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:649) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:635) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1355) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:717) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2723) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1914) 
03-21 22:13:06.197: E/AndroidRuntime(25342): at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:122) 
03-21 22:13:06.197: E/AndroidRuntime(25342): ... 15 more 

Da quello che ho capito, non sta riconoscendo la mia classe Loja. Ma sono esattamente uguali! Cos'altro potrebbe essere?

risposta

9

L'eccezione sembra suggerire che mentre il mappatore Jackson sta cercando di creare un Loja dal json restituito, ha incontrato un campo JSON con una chiave di Loja, che non sapeva come gestire (perché non ci sono campi nell'oggetto java Loja denominato "Loja"), quindi non è riuscito. Questo sembra logico, perché sembra che il server è effettivamente tornando tale struttura JSON:

{"Loja":{"nome":"teste","xValue":"20","yValue":"30","andar":"1"}} 

A causa di questo, si hanno due opzioni principali.

  1. modificare l'oggetto che viene passato al getForObject() o
  2. Modificare il JSON restituito dal server.

Per il primo, si può avere il client di fare un getForObject() passando in un Object che contiene un Loja.

Qualcosa di simile a questa classe:

class MyObj { 
    private Loja Loja; 

    public void setLoja(Loja loja) { 
     this.Loja = loja; 
    } 

    public Loja getLoja() { 
     return this.Loja; 
    } 
} 

essere utilizzato con questo invito:

restTemplate.getForObject(url, MyObj.class); 

In alternativa, si potrebbe avere il server restituisce il Loja oggetti campi come parte del modello, o meglio ancora, restituisci l'istanza dell'oggetto Loja che hai creato. Spring è abbastanza intelligente da utilizzare Jackson per trasformare i tuoi POJO nel modello JSON che ti aspetti.

@RequestMapping("/android/played") 
public Loja getLoja() { 
    System.out.println("Android Resquest."); 

    return new Loja("teste", "20", "30", "1"); 
} 

che produrrebbe questo JSON:

{"nome":"teste","xValue":"20","yValue":"30","andar":"1"} 

Che sarebbe leggibile dal tuo metodo di getForObject() sul lato client solo il modo in cui è attualmente.

+1

Grazie per la risposta, ma non funziona .. Avevi ragione riguardo al fatto che il json prodotto, non so perché, ma sta creando un campo "Loja" all'inizio della stringa. Ho provato a cambiare il mio getLoja() ritorno a Loja come suggerito, ma sto ancora ricevendo lo stesso json .. con il tuo suggerimento il json prodotto è: {"loja": {"nome": "teste", "xValue ":" 20 "," yValue ":" 30 "," andar ":" 1 "}} –

+1

Quali modifiche hai apportato? Credo di aver offerto un paio di soluzioni potenziali, non una soluzione unica. Potresti aggiornare la tua domanda con le modifiche che hai apportato che non funzionano? –

+1

Grazie per le tue idee! Ha aiutato a capire come risolverlo! Ho postato una risposta spiegando come l'ho fatto. Dategli un'occhiata –

2

Ho scoperto che cosa era sbagliato con il mio codice.Nicholas aveva ragione, il mio JSON era qualcosa di simile:

{"Loja":{"nome":"teste","xValue":"20","yValue":"30","andar":"1"}} 

e il campo Loja non veniva riconosciuto quando inviato a un'applicazione Android.

Ecco cosa ho fatto: ho creato un'altra classe chiamata Lojas che non ha nient'altro che una lista Loja.

public class Lojas { 

    private List<Loja> lojas; 

    public Lojas() { 
    } 

    public List<Loja> getLojas() { 
     return lojas; 
    } 

    public void setLojas(List<Loja> lojas) { 
     this.lojas = lojas; 
    } 
} 

nel mio metodo getLoja(), che sto tornando questo nuovo metodo di creazione:

public Lojas getLoja() { 
     RestTemplate restTemplate = new RestTemplate(); 
     restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter()); 
     restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); 

     String url = BASE_URL + "/android/played.json"; 
     return restTemplate.getForObject(url, Lojas.class); 
    } 

questo modo, posso richiedere un elenco di oggetti Loja in una sola volta. ma per farlo ho dovuto cambiare lato server per restituire sempre un elenco di oggetti Loja:

@RequestMapping("/android/played") 
    public ModelAndView getLoja() { 
     System.out.println("Android Request."); 

     List<Loja> list = new ArrayList<Loja>(); 
     list.add(new Loja("teste", "20", "30", "1")); 
     list.add(new Loja("teste2", "20", "30", "1")); 
     ModelAndView mav = new ModelAndView(); 
     mav.addObject("lojas", list); 
     return mav; 
    } 
+2

Avresti dovuto accettare la risposta di @ nicholas.hauschild e poi rispondere anche se volevi aggiungere altri dettagli per gli altri. Ha fatto il lavoro e la sua risposta ti ha portato alla soluzione. – Gray

2

ho risolto questo problema facendo una JSON Post utilizzando RestTemplate.

HTTP_HEADERS.setContentType(MediaType.APPLICATION_JSON); 

final ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); 
final String body = ow.writeValueAsString(convertedFireCsvBeans); 
final HttpEntity<String> entity = new HttpEntity<>(body, HTTP_HEADERS); 
final ParameterizedTypeReference<String> responseType = new ParameterizedTypeReference<String>(){}; 
final ResponseEntity<String> responseEntity = REST_TEMPLATE.exchange(url, HttpMethod.POST, entity, responseType); 
if(responseEntity.getStatusCode() != null){ 
      System.out.println("HTTP STATUS CODE: " + responseEntity.getStatusCode() + 
         "\n"+ responseEntity.getStatusCode().getReasonPhrase()); 
        httpStatus = responseEntity.getStatusCode();      
       } 

La cosa principale è che il mio HttpEntity ho dovuto impostare a String.

Spero possa aiutare qualcuno.

Problemi correlati