web-dev-qa-db-ja.com

HttpMessageNotReadableException:JSONを読み取ることができませんでした:Android

開発中です。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

私が失望したことによって、それは私のロハのクラスを認識していません。しかし、それらはまったく同じです!他に何がありますか?

10
Felipe Mosso

例外は、Jacksonマッパーが返されたjsonからLojaを作成しようとしているときに、Lojaのキーを持つjsonフィールドに遭遇したことを示唆しているようです。 Loja Java "Loja"という名前のオブジェクト)にフィールドがないため、失敗しました。これは論理的に思えます。

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

このため、2つの主要なオプションがあります。

  1. getForObject()に渡されるオブジェクトを変更するか、
  2. サーバーから返されたJSONを変更します。

最初の方法では、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()メソッドで現在の方法で読み取ることができます。

11

私はこの問題を解決してJSON PostRestTemplateを使用します。

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

主なことは、私のHttpEntityStringに設定しなければならなかったことです。

それが誰かを助けることを願っています。

2
José Mendes

私はコードのどこがおかしいのかを発見しました。ニコラスは正しかった、私の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;
    }
2
Felipe Mosso

私の場合、空のコンストラクタを明示的に定義すると役立ちました。そうしないと、restTemplateを使用したテストが失敗します。

0
mykey