開発中です。Androidサーバーと通信するアプリケーション。この通信は、Springフレームワークとジャクソンを介して行われます。サーバーへのリクエストを正常に送信していますが、応答が得られません。ここに私がやったことがあります:
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);
}
Lojaクラス(2つのバージョンがあります。1つはAndroidアプリにあり、もう1つはサーバーにあります。これらは完全に同じです):
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;
}
}
そして、ここに私のコントローラーがあります:
@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;
}
このすべてで、Android app:
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: org.Apache.http.conn.EofSensorInputStream@422e3c58; 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: org.Apache.http.conn.EofSensorInputStream@422e3c58; 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: org.Apache.http.conn.EofSensorInputStream@422e3c58; 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
私が失望したことによって、それは私のロハのクラスを認識していません。しかし、それらはまったく同じです!他に何がありますか?
例外は、Jacksonマッパーが返されたjsonからLoja
を作成しようとしているときに、Lojaのキーを持つjsonフィールドに遭遇したことを示唆しているようです。 Loja
Java "Loja"という名前のオブジェクト)にフィールドがないため、失敗しました。これは論理的に思えます。
_{"Loja":{"nome":"teste","xValue":"20","yValue":"30","andar":"1"}}
_
このため、2つの主要なオプションがあります。
getForObject()
に渡されるオブジェクトを変更するか、最初の方法では、Object
を含むLoja
を渡すgetForObject()
をクライアントに実行させることができます。
このクラスのようなもの:
_class MyObj {
private Loja Loja;
public void setLoja(Loja loja) {
this.Loja = loja;
}
public Loja getLoja() {
return this.Loja;
}
}
_
この呼び出しで使用されています:
_restTemplate.getForObject(url, MyObj.class);
_
または、サーバーにLoja
オブジェクトフィールドをモデルの一部として返させるか、さらに良いことに、作成したLoja
オブジェクトのインスタンスを返させることができます。 Springは、Jacksonを使用してPOJOを期待する適切なJSONモデルに変換するのに十分なほどスマートです。
_@RequestMapping("/Android/played")
public Loja getLoja() {
System.out.println("Android Resquest.");
return new Loja("teste", "20", "30", "1");
}
_
これはこのjsonを生成します:
_{"nome":"teste","xValue":"20","yValue":"30","andar":"1"}
_
これは、クライアント側のgetForObject()
メソッドで現在の方法で読み取ることができます。
私はこの問題を解決してJSON Post
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();
}
主なことは、私のHttpEntity
をString
に設定しなければならなかったことです。
それが誰かを助けることを願っています。
私はコードのどこがおかしいのかを発見しました。ニコラスは正しかった、私のJSONは次のようなものでした:
{"Loja":{"nome":"teste","xValue":"20","yValue":"30","andar":"1"}}
また、Android application。
これが私がしたことです。私はLojasと呼ばれる別のクラスを作成しました。
public class Lojas {
private List<Loja> lojas;
public Lojas() {
}
public List<Loja> getLojas() {
return lojas;
}
public void setLojas(List<Loja> lojas) {
this.lojas = lojas;
}
}
getLoja()メソッドで、作成されたこの新しいメソッドを返します。
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);
}
このようにして、Lojaオブジェクトのリストを一度に要求できます。しかし、それを行うには、常に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;
}
私の場合、空のコンストラクタを明示的に定義すると役立ちました。そうしないと、restTemplateを使用したテストが失敗します。