簡體   English   中英

為什么我的應用無法從我的API讀取JSON?

[英]Why do my App cant read a JSON from my API?

我正在使用Retrofit 2,並且試圖從我使用Python制作的Web服務中請求一些數據。

實際上,它會引發“ java.lang.IllegalStateException”,但是當我調用GET方法時,API返回代碼200,並且我還可以看到用於調試響應JSON的打印版本。 問題是Call方法,因為它始終執行OnFailure。

請幫忙!

這是我的(簡單)Python Web服務api-prueba:

from flask import Flask, jsonify
    import json
    import mysql.connector
    import collections

    app = Flask(__name__)

    cnx = mysql.connector.connect(user="root", password="", host="localhost", database="gym")


    @app.route('/gym/api/v1.0/clases', methods=['GET'])
    def getClases():
        sql = "SELECT id, nombre, descripcion FROM clases"

        cursor = cnx.cursor()
        cursor.execute(sql)
        entradas = cursor.fetchall()

        # Convertir la query en un array de entradas

        objects_list = []
        for row in entradas:
            objects_list.append(row)
            j = json.dumps(objects_list)
        return j

    @app.route('/')
    def index():
        return 'Hello, World!'

    if __name__ == '__main__':
        app.run(debug=True)

這是我的ApiClient:

public class ApiClient {

    private static ApiService REST_CLIENT;
    private static final String API_URL = "http://10.0.2.2:5000/gym/api/v1.0/"; //Change according to your API path.

    static {
        setupRestClient();
    }

    private ApiClient() {
    }

    public static ApiService get() {
        return REST_CLIENT;
    }

    private static void setupRestClient() {

        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

        //Uncomment these lines below to start logging each request.


            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            httpClient.addInterceptor(logging);
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(API_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(httpClient.build())
                    .build();
            REST_CLIENT = retrofit.create(ApiService.class);
        }
    }

我的API接口,ApiService:

public interface ApiService {
       @GET("clases")
       Call> getClases();
    }

這是查詢API並獲取數據的片段ClaseFragment:

public class ClaseFragment extends Fragment implements View.OnClickListener {

    private List clases;
    private ListView listView;

    private Button btnRefresh;

    public ClaseFragment() {
        // Required empty public constructor
    }

    public static ClaseFragment newInstance() {
        ClaseFragment fragment = new ClaseFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {

        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View root = inflater.inflate(R.layout.fragment_clase, container, false);

        listView = (ListView) root.findViewById(R.id.claseList);
        btnRefresh = (Button) root.findViewById(R.id.btnRefresh);
        btnRefresh.setOnClickListener(this);
        getListaClases();

        return root;
     }


      @Override
      public void onClick(View v) {
        //do what you want to do when button is clicked
        switch (v.getId()) {
            case R.id.btnRefresh:
                Log.d(getTag(), "hello");
                getListaClases();
                break;
            default:
                break;
        }
    }

     private void getListaClases() {
        final ProgressDialog loading = ProgressDialog.show(getActivity(),
                getContext().getString(R.string.loading_title),
                getContext().getString(R.string.loading_please_wait),
                false,
                false);

        Call> call = ApiClient.get().getClases();

        call.enqueue(new Callback>() {
            @Override
            public void onFailure(Call> call, Throwable t) {
                Log.d("ApiService", "Error Occured: " + t.getMessage());

                loading.dismiss();
            }

            @Override
            public void onResponse(Call> call, Response> response) {
                Log.d("ApiService", "Successfully response fetched");

                loading.dismiss();
                if (response.code() == 200 && response.isSuccessful()) {
                    clases = response.body();
                    showList();
                } else {
                    Log.d("APIPlug", "No item found");
                }
            }
        });
    }

    //Our method to show list
     private void showList() {
        Log.d("ApiService", "Show List");

        ClaseAdapter adapter = new ClaseAdapter(getActivity(), clases);

        listView.setAdapter(adapter);


        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                Clase clickedObj = (Clase) parent.getItemAtPosition(position);

                //If you have detail activity about your object define in here
            /*
            Intent detail = new Intent(getContext(), ActorDetail.class);
            detail.putExtra("actorObject", clickedObj);
            startActivity(detail);
            */
            }
        });

    }


    }

這是我要顯示在ListView中的Web服務的實際響應:

 [
    [1, "halterofilia", "Profesor: XXXX YYYY. Clase de Halterofilia."],
    [2, "crossfit", "Profesor:ZZZZ TTTT. Clase de CrossFit"],
    [3, "halterofilia", "Profesor:XXXX YYYY. Clase de halterofilia"]
 ]

編輯:

從Android Studio追溯:

 D/OkHttp: --> GET http://10.0.2.2:5000/gym/api/v1.0/clases http/1.1
 D/OkHttp: --> END GET
 D/OkHttp: <-- 200 OK http://10.0.2.2:5000/gym/api/v1.0/clases (8ms)
 D/OkHttp: Content-Type: text/html; charset=utf-8
 D/OkHttp: Content-Length: 192
 D/OkHttp: Server: Werkzeug/0.11.11 Python/2.7.12
 D/OkHttp: Date: Sat, 08 Oct 2016 23:19:00 GMT
 D/OkHttp: OkHttp-Sent-Millis: 1475968739892
 D/OkHttp: OkHttp-Received-Millis: 1475968739897
 D/OkHttp: [[1, "halterofilia", "Profesor: XXXX YYYY. Clase de   Halterofilia."], [2, "crossfit", "Profesor:ZZZZ TTTT. Clase de CrossFit"], [3,   "halterofilia", "Profesor:XXXX YYYY. Clase de halterofilia"]]
 D/OkHttp: <-- END HTTP (192-byte body)
 D/ApiService: Error Occured: java.lang.IllegalStateException: Expected          BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0]

這是從PyCharm運行我的Web服務的地方:

  * Detected change in 'D:\\Proyectos\\PyCharm\\api-prueba\\api-prueba.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 195-275-846
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [09/Oct/2016 00:21:38] "GET /gym/api/v1.0/clases HTTP/1.1" 200 -

D / ApiService:錯誤發生:java.lang.IllegalStateException:預期為BEGIN_OBJECT,但在第1行第3列路徑$ [0]中為BEGIN_ARRAY

從這個錯誤中,您可以說這與預期的升級以及您的API給您的不一致。 更具體地說,看起來改造是期望一個對象,但是您的API返回一個數組。 我想您正在嘗試獲取Clases對象的列表,而您的API發送的是一個...數組。

為此,我將嘗試獲取如下所示的API響應:

[
    {"id": 1, "name": "halterofilia", "title": "Profesor: XXXX YYYY. Clase de Halterofilia."},
    {"id": 2, "name": "crossfit", "title": "Profesor:ZZZZ TTTT. Clase de CrossFit"},
    {"id": 3, "name": "halterofilia", "title": "Profesor:XXXX YYYY. Clase de halterofilia"}
]

(標識,名稱和標題將由您的數據庫字段的實際名稱替換)

這是一個應該指導您如何實現python代碼更改的鏈接: Python將mysql查詢結果轉換為json

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM