Volley - 使用JSONArrayRequest发送POST请求

19

我正在使用Volley与API进行交互。我需要向返回JSON数组的服务发送带参数的POST请求。

JsonObjectRequest有一个构造函数,它接受一个方法和一组参数。

JsonObjectRequest(int method, java.lang.String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) 

然而,JSONArrayRequest(我需要的那个)只有一个表单形式的构造函数。

JsonArrayRequest(java.lang.String url, Response.Listener<JSONArray> listener, Response.ErrorListener errorListener) 

我应该如何使它发送带有数据的POST请求?

9个回答

50

他们可能会在以后添加它,但同时您可以自己添加所需的构造函数:

public JsonArrayRequest(int method, String url, JSONObject jsonRequest,
        Listener<JSONArray> listener, ErrorListener errorListener) {
    super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), 
        listener, errorListener);
}

虽然我没有测试过,但是我认为这应该可以工作,因为实现细节在超类JsonRequest中。

尝试一下,看看是否有效。

编辑:

我猜对了!我回答这个问题后他们花了将近两年时间,但Volley团队于2015年3月19日将此构造函数添加到代码库中。你知道吗?这就是确切的语法。


其实昨晚我自己在代码中探索时发现了这个。不过还是谢谢你。它运行得非常好。 - Marc Mailhot
你好,实际上你在哪里编写这段代码?而且super(...)是如何工作的呢?因为默认构造函数是这样的:JsonArrayRequest(java.lang.String url,Response.Listener<org.json.JSONArray> listener,ErrorListener errorListener)。 - FlavienBert
超级构造函数属于“父类”JsonRequest<JSONArray>,JsonArrayRequest继承自该类,因此它可以正常工作。我认为您将其与使用“this”调用构造函数混淆了。您需要将该代码添加到JsonArrayRequest.java(位于toolbox包内)。 - Itai Hanski
1
这是一个被接受的答案,有8个赞。这可能意味着你的问题不在于这个构造函数,而是在于你的服务器响应。调试你的代码并查看。 - Itai Hanski
1
请注意:官方的Volley库没有这个构造函数。这个可以在已弃用和非官方的Volley库中找到:https://github.com/mcxiaoke/android-volley - Donovan Keating

7

我很懒,没有自己构建Volley库(只使用了.jar文件),因此没有源代码...所以在匿名的新JSONArrayRequest中,我添加了这些函数:

            // NO CONSTRUCTOR AVAILABLE FOR POST AND PARAMS FOR JSONARRAY!
            // overridden the necessary functions for this
            @Override
            public byte[] getBody() {
                try {
                    return paramsArray.toString().getBytes("utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public int getMethod() {
                return Method.POST;
            }

你的回答对于刚使用 .jar 的初学者来说更容易理解。@Itai 的回答让像我这样的初学者感到困惑。 - Yakob Ubaidi
是的,你可以直接子类化JSONArrayRequest,而不必重新编写它。 - kaay
什么是参数数组? - kuldeep
1
@k2ibegin 不太确定了XD,但我猜那只是服务器需要的数据列表。不过我想它可以是任何你想要的东西。 - Boy

2

使用JSONarray请求发送参数请求并根据参数返回自定义响应的最佳简单方法是将获取参数值添加到URL本身中。

String URL ="http://mentormentee.gear.host/android_api/Message.aspx?key="+keyvalue;

keyvalue 参数值添加到 URL 中,然后将该 URL 添加到 JsonArrayRequest URL 中即可。

    JsonArrayRequest searchMsg= new JsonArrayRequest(URL, new Response.Listener<JSONArray>() {

        @Override
        public void onResponse(JSONArray response) {
            Log.d(TAG, response.toString());


            // Parsing json
            for (int i = 0; i < response.length(); i++) {
                try {

                    JSONObject obj = response.getJSONObject(i);
                    Message msg = new Message();
                    msg.setMessageThread(obj.getString("msgThread"));
                    msg.setUserName(obj.getString("Username"));
                    msg.setDate(obj.getString("msgDate"));

                    // adding movie to movies array
                    MessageList.add(msg);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }

            // notifying list adapter about data changes
            // so that it renders the list view with updated data
            adapter.notifyDataSetChanged();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
           // hidePDialog();

        }
    });
    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(searchMsg);
}

需要在服务器端的PHP上添加额外的东西吗? - techDigi

2

这段代码可以实现您想要的功能。

    Volley.newRequestQueue(context).add(
            new JsonRequest<JSONArray>(Request.Method.POST, "url/", null,
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray response) {

                        }
                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {

                        }
                    }) {
                @Override
                protected Map<String, String> getParams() {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("param1", "one");
                    params.put("param2", "two");
                    return params;
                }

                @Override
                protected Response<JSONArray> parseNetworkResponse(
                        NetworkResponse response) {
                    try {
                        String jsonString = new String(response.data,
                                HttpHeaderParser
                                        .parseCharset(response.headers));
                        return Response.success(new JSONArray(jsonString),
                                HttpHeaderParser
                                        .parseCacheHeaders(response));
                    } catch (UnsupportedEncodingException e) {
                        return Response.error(new ParseError(e));
                    } catch (JSONException je) {
                        return Response.error(new ParseError(je));
                    }
                }
            });

1
使用 getParam() 发送的奇怪数据在服务器上没有接收到,否则它正常工作。为什么? - Pablo Escobar

1
You can use this 

package HelperClass;
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * A request for retrieving a {@link JSONArray} response body at a given URL.enter code here
 */
public class MyjsonPostRequest extends JsonRequest<JSONArray> {

    protected static final String PROTOCOL_CHARSET = "utf-8";



    /**
     * Creates a new request.
     * @param method the HTTP method to use
     * @param url URL to fetch the JSON from
     * @param requestBody A {@link String} to post with the request. Null is allowed and
     *   indicates no parameters will be posted along with request.
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public MyjsonPostRequest(int method, String url, String requestBody,
                            Listener<JSONArray> listener, ErrorListener errorListener) {
        super(method, url, requestBody, listener,
                errorListener);
    }

    /**
     * Creates a new request.
     * @param url URL to fetch the JSON from
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public MyjsonPostRequest(String url, Listener<JSONArray> listener, ErrorListener errorListener) {
        super(Method.GET, url, null, listener, errorListener);
    }

    /**
     * Creates a new request.
     * @param method the HTTP method to use
     * @param url URL to fetch the JSON from
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public MyjsonPostRequest(int method, String url, Listener<JSONArray> listener, ErrorListener errorListener) {
        super(method, url, null, listener, errorListener);
    }

    /**
     * Creates a new request.
     * @param method the HTTP method to use
     * @param url URL to fetch the JSON from
     * @param jsonRequest A {@link JSONArray} to post with the request. Null is allowed and
     *   indicates no parameters will be posted along with request.
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public MyjsonPostRequest(int method, String url, JSONArray jsonRequest,
                            Listener<JSONArray> listener, ErrorListener errorListener) {
        super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
                errorListener);
    }

    /**
     * Creates a new request.
     * @param method the HTTP method to use
     * @param url URL to fetch the JSON from
     * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and
     *   indicates no parameters will be posted along with request.
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public MyjsonPostRequest(int method, String url, JSONObject jsonRequest,
                            Listener<JSONArray> listener, ErrorListener errorListener) {
        super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
                errorListener);
    }

    /**
     * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is
     * <code>null</code>, <code>POST</code> otherwise.
     *
     * @see #MyjsonPostRequest(int, String, JSONArray, Listener, ErrorListener)
     */
    public MyjsonPostRequest(String url, JSONArray jsonRequest, Listener<JSONArray> listener,
                            ErrorListener errorListener) {
        this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest,
                listener, errorListener);
    }

    /**
     * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is
     * <code>null</code>, <code>POST</code> otherwise.
     *
     * @see #MyjsonPostRequest(int, String, JSONObject, Listener, ErrorListener)
     */
    public MyjsonPostRequest(String url, JSONObject jsonRequest, Listener<JSONArray> listener,
                            ErrorListener errorListener) {
        this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest,
                listener, errorListener);
    }

    @Override
    protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONArray(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

}

1
也许你的问题已经解决了,但我希望这对其他用户有所帮助。我的做法是创建一个新的自定义类并进行扩展。以下是代码:
public class CustomJsonRequest extends Request {

Map<String, String> params;       
private Response.Listener listener; 

public CustomJsonRequest(int requestMethod, String url, Map<String, String> params,
                      Response.Listener responseListener, Response.ErrorListener errorListener) {

    super(requestMethod, url, errorListener);
    this.params = params;
    this.listener = responseListener;
}

@Override
protected void deliverResponse(Object response) {
    listener.onResponse(response); 

}

@Override
public Map<String, String> getParams() throws AuthFailureError {
         return params;
}

@Override
protected Response parseNetworkResponse(NetworkResponse response) {
    try {
        String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        return Response.success(new JSONObject(jsonString),
        HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JSONException je) {
        return Response.error(new ParseError(je));
    }
}

}

你可以使用这个类来替代JsonArrayRequest或JSonObjectRequest。而且这也解决了php无法捕获$_POST中的post参数的问题。

实际上它是有效的,但我需要其他东西。在我的情况下,我的参数是一个Json对象或者有时是一个Json数组。我该如何使用你的代码来满足我的需求? - FlavienBert
@FlavienBert 你可以对JSON对象进行类型检查,以确定需要返回数组还是对象。 Object json = new JSONTokener(jsonString).nextValue(); if (json instanceof JSONObject) { } else if (json instanceof JSONArray) { } - JeffRegan
哦,谢天谢地!我一直在苦苦思索这个问题,但是这个方法起作用了,只需要将return Response.success(new JSONArray(jsonString),改为JSONArray以满足我的需求。然而,我很好奇为什么我自己的方法会遇到困难,如果您有时间并且不介意看一下,我在这里发布了一个帖子[链接](http://stackoverflow.com/questions/29837859/using-custom-volley-post-doesnt-return-anything)。 - Wingman1487

0
JsonArrayRequest req = new JsonArrayRequest(urlJsonArry,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, response.toString());

                        try {
                            // Parsing json array response
                            // loop through each json object
                            jsonResponse = "";
                            for (int i = 0; i < response.length(); i++) {

                                JSONObject person = (JSONObject) response
                                        .get(i);

                                String name = person.getString("name");
                                String email = person.getString("email");
                                JSONObject phone = person
                                        .getJSONObject("phone");
                                String home = phone.getString("home");
                                String mobile = phone.getString("mobile");

                                jsonResponse += "Name: " + name + "\n\n";
                                jsonResponse += "Email: " + email + "\n\n";
                                jsonResponse += "Home: " + home + "\n\n";
                                jsonResponse += "Mobile: " + mobile + "\n\n\n";

                            }

                            txtResponse.setText(jsonResponse);

                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toast.makeText(getApplicationContext(),
                                    "Error: " + e.getMessage(),
                                    Toast.LENGTH_LONG).show();
                        }

                        hidepDialog();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d(TAG, "Error: " + error.getMessage());
                        Toast.makeText(getApplicationContext(),
                                error.getMessage(), Toast.LENGTH_SHORT).show();
                        hidepDialog();
                    }
                });

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(req);

}


0
List<Map<String,String>> listMap =  new ArrayList<Map<String, String>>();
        Map<String,String> map  = new HashMap<String,String>();
        try {

            map.put("email", customer.getEmail());
            map.put("password",customer.getPassword());

        } catch (Exception e) {
            e.printStackTrace();
        }
        listMap.add(map);

        String url = PersonalConstants.BASE_URL+"/url";
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
                Request.Method.POST, url, String.valueOf(new JSONArray(listMap)),
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {
                        Log.d(App.TAG, jsonObject.toString());
                    }
                }, new Response.ErrorListener (){

            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d(App.TAG,volleyError.toString());
            }
        }
        );
        App.getInstance().getmRequestQueue().add(jsonObjectRequest);

0

请添加有关JsonArrayRequest的详细信息。 在\src\com\android\volley\toolbox中,您可以发现JsonArrayRequest的默认构造不支持Method参数,并且Volley在构造函数中添加了方法(GET), 因此,如果您想使用其他方法,请尝试自行编写。

public class JsonArrayRequest extends JsonRequest<JSONArray> {

    /**
     * Creates a new request.
     * @param url URL to fetch the JSON from
     * @param listener Listener to receive the JSON response
     * @param errorListener Error listener, or null to ignore errors.
     */
    public JsonArrayRequest(String url, Listener<JSONArray> listener, ErrorListener errorListener) {
        super(Method.GET, url, null, listener, errorListener);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接