2013-03-22 8 views
7

Tôi đang phát triển và ứng dụng Android giao tiếp với Máy chủ của tôi. Giao tiếp này được thực hiện thông qua khung Spring và Jackson. Tôi đang gửi yêu cầu cho máy chủ của mình thành công nhưng tôi không nhận được phản hồi. Dưới đây là những gì tôi đã làm:HttpMessageNotReadableException: Không thể đọc JSON: Trường không được công nhận bằng Spring cho Android

Android ứng dụng:

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

Loja lớp (Tôi có hai phiên bản của nó Một trong ứng dụng Android và khác trong Server Họ là hoàn toàn giống nhau..):

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

} 

Và đây là bộ điều khiển của tôi:

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

với tất cả những điều tôi nhận được ngoại lệ followin trong ứng dụng 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 

Bằng những gì tôi không hiểu, nó không nhận ra lớp Loja của tôi. Nhưng chúng hoàn toàn giống nhau! Còn gì nữa?

Trả lời

9

Ngoại lệ dường như gợi ý rằng trong khi người lập bản đồ Jackson đang cố gắng tạo ra một số Loja từ json được trả về, nó gặp phải trường json với khóa của Loja, mà nó không biết cách xử lý (vì không có các trường trong đối tượng java Loja có tên "Loja"), do đó, nó không thành công. Điều này có vẻ hợp lý, vì có vẻ như máy chủ đang trả lại cấu trúc json này một cách hiệu quả:

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

Do đó, bạn có hai lựa chọn chính.

  1. Thay đổi đối tượng đó sẽ được chuyển cho getForObject() hoặc
  2. Thay đổi json trở về từ máy chủ.

Đối với người đầu tiên, bạn có thể yêu cầu khách hàng của mình làm getForObject() chuyển vào số Object có chứa Loja.

Something như lớp này:

class MyObj { 
    private Loja Loja; 

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

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

được sử dụng với cuộc gọi này:

restTemplate.getForObject(url, MyObj.class); 

Ngoài ra, bạn có thể có máy chủ của bạn trả lại Loja đối tượng lĩnh vực như là một phần của mô hình, hoặc tốt hơn chưa, trả về cá thể của đối tượng Loja mà bạn đã tạo. Mùa xuân đủ thông minh để sử dụng Jackson để biến POJO của bạn thành mô hình json thích hợp mà bạn mong đợi.

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

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

nào sẽ tạo ra json này:

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

Trong đó sẽ có thể đọc được bằng phương pháp getForObject() của bạn trên các mặt hàng chỉ là cách nó hiện là.

+1

Cảm ơn bạn đã trả lời, nhưng nó không hoạt động .. Bạn đã đúng về việc sản xuất json, tôi không biết tại sao, nhưng nó đang tạo ra một trường "Loja" lúc bắt đầu chuỗi. Tôi đã cố gắng để thay đổi getLoja của tôi() trở lại Loja như bạn đề nghị, nhưng tôi vẫn nhận được cùng một json .. với đề xuất của bạn json sản xuất là: {"loja": {"nome": "teste", "xValue ":" 20 "," yValue ":" 30 "," andar ":" 1 "}} –

+1

Bạn đã thực hiện những thay đổi nào? Tôi tin rằng tôi đã cung cấp một vài giải pháp tiềm năng, không phải là một giải pháp duy nhất. Bạn có thể cập nhật câu hỏi của mình với những thay đổi bạn đã thực hiện không hoạt động không? –

+1

Cảm ơn ý kiến ​​của bạn! Nó đã giúp tìm ra cách để giải quyết nó! Tôi đã đăng một câu trả lời giải thích làm thế nào tôi đã làm nó. Kiểm tra nó ra –

2

Tôi đã phát hiện thấy có gì sai với mã của mình.Nicholas đã đúng, JSON của tôi giống như:

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

và trường Loja không được công nhận khi được gửi đến ứng dụng Android.

Đây là những gì tôi đã làm: Tôi đã tạo một lớp khác có tên Lojas không có gì khác ngoài Danh sách 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; 
    } 
} 

trong phương pháp của tôi getLoja(), tôi trở về thương hiệu này phương pháp mới tạo ra:

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

cách này, tôi có thể yêu cầu một Danh sách đối tượng Loja cùng một lúc. nhưng để làm điều đó tôi đã phải thay đổi phía máy chủ để luôn trả về một Danh sách đối tượng 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

Bạn thực sự cần phải chấp nhận câu trả lời của @ nicholas.hauschild và sau đó cũng trả lời nó nếu bạn muốn thêm chi tiết cho người khác. Ông đã làm công việc và câu trả lời của ông dẫn bạn đến giải pháp. – Gray

2

tôi giải quyết vấn đề này thực hiện một JSON Post sử dụng 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();      
       } 

Điều chính là tôi HttpEntity Tôi phải đặt thành String.

Tôi hy vọng nó có thể giúp ai đó.