Volley JsonObjectRequest Post 参数不再起作用

Posted

技术标签:

【中文标题】Volley JsonObjectRequest Post 参数不再起作用【英文标题】:Volley JsonObjectRequest Post parameters no longer work 【发布时间】:2015-06-09 04:19:51 【问题描述】:

我正在尝试在 Volley JsonObjectRequest 中发送 POST 参数。最初,它对我有用,按照官方代码所说的在 JsonObjectRequest 的构造函数中传递包含参数的 JSONObject。然后突然之间它停止工作,我没有对以前工作的代码进行任何更改。服务器不再识别正在发送的任何 POST 参数。这是我的代码:

RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://myserveraddress";

// POST parameters
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "test");

JSONObject jsonObj = new JSONObject(params);

// Request a json response from the provided URL
JsonObjectRequest jsonObjRequest = new JsonObjectRequest
        (Request.Method.POST, url, jsonObj, new Response.Listener<JSONObject>()
        
            @Override
            public void onResponse(JSONObject response)
            
                Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_SHORT).show();
            
        ,
        new Response.ErrorListener()
        
            @Override
            public void onErrorResponse(VolleyError error)
            
                Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_SHORT).show();
            
        );

// Add the request to the RequestQueue.
queue.add(jsonObjRequest);

这是服务器上的简单测试器 php 代码:

$response = array("tag" => $_POST["tag"]);
echo json_encode($response);

我得到的回复是"tag":null 昨天,它运行良好,并回复"tag":"test" 我没有改变任何东西,但今天它不再起作用了。

在 Volley 源代码构造函数 javadoc 中,它说您可以在构造函数中传递 JSONObject 以在“@param jsonRequest”处发送 post 参数: https://android.googlesource.com/platform/frameworks/volley/+/master/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java

/** * 创建一个新请求。 * @param method 要使用的 HTTP 方法 * @param url 获取 JSON 的 URL * @param jsonRequest 与请求一起发布的 @link JSONObject。允许为空并且 *       表示不会随请求一起发布任何参数。

我已阅读其他类似问题的帖子,但解决方案对我不起作用:

Volley JsonObjectRequest Post request not working

Volley Post JsonObjectRequest ignoring parameters while using getHeader and getParams

Volley not sending a post request with parameters.

我尝试将 JsonObjectRequest 构造函数中的 JSONObject 设置为 null,然后覆盖并设置“getParams()”、“getBody()”和“getPostParams()”方法中的参数,但这些都没有覆盖对我有用。另一个建议是使用一个额外的帮助类,它基本上创建了一个自定义请求,但是这个修复对于我的需要来说有点太复杂了。如果归根结底,我会做任何事情来使它工作,但我希望有一个简单的原因来解释为什么我的代码 工作,然后只是停止,也是一个简单的解决方案。

【问题讨论】:

你找到解决办法了吗? @Dory 是的,我确实找到了一个简单的解决方案。它没有解决 JsonObjectRequest 的问题,我只是完全放弃了 JsonObjectRequest,因为解决方案是改用 Volley 的 StringRequest。在下面查看我的答案,看看我做了什么。 查看此链接***.com/questions/19837820/…。 ***.com/questions/34367435/… 谁能解决? 【参考方案1】:

您只需从参数的 HashMap 中创建一个 JSONObject:

String url = "https://www.youraddress.com/";

Map<String, String> params = new HashMap();
params.put("first_param", 1);
params.put("second_param", 2);

JSONObject parameters = new JSONObject(params);

JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.POST, url, parameters, new Response.Listener<JSONObject>() 
    @Override
    public void onResponse(JSONObject response) 
        //TODO: handle success
    
, new Response.ErrorListener() 
    @Override
    public void onErrorResponse(VolleyError error) 
        error.printStackTrace();
        //TODO: handle failure
    
);

Volley.newRequestQueue(this).add(jsonRequest);

【讨论】:

正确。这正是我所做的。请查看我发布的示例代码。起初它工作,但突然停止工作。但是,我一直使用 StringRequest 作为我的解决方案,此后没有遇到任何问题。 我有个疑问,这里的方法名在哪里? 这里没有方法,所以你不会看到任何方法名称 :p 这只是一些你可以放在你自己方法中的代码;)【参考方案2】:

我最终改用 Volley 的 StringRequest,因为我花费了太多宝贵的时间来尝试使 JsonObjectRequest 工作。

RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://myserveraddress";

StringRequest strRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>()
                
                    @Override
                    public void onResponse(String response)
                    
                        Toast.makeText(getApplicationContext(), response, Toast.LENGTH_SHORT).show();
                    
                ,
                new Response.ErrorListener()
                
                    @Override
                    public void onErrorResponse(VolleyError error)
                    
                        Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_SHORT).show();
                    
                )
        
            @Override
            protected Map<String, String> getParams()
            
                Map<String, String> params = new HashMap<String, String>();
                params.put("tag", "test");
                return params;
            
        ;

queue.add(strRequest);

这对我有用。它和 JsonObjectRequest 一样简单,但是使用了 String。

【讨论】:

它在 android 5.1.1 上得到一个错误响应,虽然在 android 4.2 上工作 收到错误 BasicNetwork.performRequest: Unexpected response code 500 for @Joshua C. 这节省了我数小时无休止的搜索。知道为什么 JSONObjectRequest 不起作用吗? @sidiabale 像你自己和 Joshua C。我想使用 JSONObjectRequest 来利用隐式 JSON 解析。令人难以置信的是,如果使用此类类型,则 POST 的参数以 JSON 格式发送。通常,无法控制服务器用于 POST 的格式。因此,如果无法自定义此行为,JSONObjectRequest 几乎毫无用处。 这很好用,但是如果你想发送一个 JSONArray 的对象呢?【参考方案3】:

我也遇到过类似的问题,但是我发现问题不在客户端,而是在服务器端。当您发送JsonObject 时,您需要像这样(在服务器端)获取 POST 对象:

在 PHP 中:

$json = json_decode(file_get_contents('php://input'), true);

【讨论】:

解决了我的问题(即使我在其他地方找到了它) 谢谢。我认为这是 OPs 问题的答案。 谢谢。不幸的是,这是真正的答案,与 JSONObjectRequest 无关 你能解释一下吗?你有php的示例代码吗? 应该代替php中的isset函数吗?【参考方案4】:

您可以使用 StringRequest 执行与 JsonObjectRequest 相同的操作,同时仍然能够轻松发送 POST 参数。您唯一需要做的就是从您获得的请求字符串中创建一个 JsonObject,然后您可以从那里继续,就好像它是 JsonObjectRequest。

StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() 
                    @Override
                    public void onResponse(String response) 
                        try 
                            //Creating JsonObject from response String
                            JSONObject jsonObject= new JSONObject(response.toString());
                            //extracting json array from response string
                            JSONArray jsonArray = jsonObject.getJSONArray("arrname");
                            JSONObject jsonRow = jsonArray.getJSONObject(0);
                            //get value from jsonRow
                            String resultStr = jsonRow.getString("result");
                         catch (JSONException e) 

                        

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

                    
                )
                    @Override
                    protected Map<String, String> getParams() throws AuthFailureError 
                        Map<String,String> parameters = new HashMap<String,String>();
                        parameters.put("parameter",param);

                        return parameters;
                    

                ;
                requestQueue.add(stringRequest);

【讨论】:

【参考方案5】:

使用 here 提到的 CustomJsonObjectRequest 帮助器类。

并像这样实现 -

CustomJsonObjectRequest request = new CustomJsonObjectRequest(Method.POST, URL, null, new Response.Listener<JSONObject>() 
    @Override
    public void onResponse(JSONObject response) 
        Toast.makeText(getActivity(), response.toString(), Toast.LENGTH_SHORT).show();
    
, new Response.ErrorListener() 
    @Override
    public void onErrorResponse(VolleyError error) 
        Toast.makeText(getActivity(), "Error.", Toast.LENGTH_SHORT).show();
    
) 
    @Override
    protected Map<String, String> getParams() throws AuthFailureError 
        Map<String, String> params = new HashMap<String, String>();
        params.put("id", id);
        params.put("password", password);
        return params;
    
;
VolleySingleton.getInstance().addToRequestQueue(request);

【讨论】:

是的,但是为什么 JsonObjectRequest 也使用 JSON 来创建 HTTP POST 请求的主体?并且考虑到正文通常以纯文本形式发送,服务器是否应该始终解码该正文以搜索可选的 JSON 内容?令人困惑...【参考方案6】:

使用 JSONObject 对象发送参数意味着参数将在 HTTP POST 请求正文中为 JSON 格式:

Map<String, String> params = new HashMap<String, String>();
params.put("tag", "test");
params.put("tag2", "test2");
JSONObject jsonObj = new JSONObject(params);

将创建此 JSON 对象并将其插入到 HTTP POST 请求的正文中:

"tag":"test","tag2":"test2"

然后服务器必须解码 JSON 以理解这些 POST 参数。

但通常 HTTP POST 参数写在正文中,如:

tag=test&tag2=test2

但现在的问题是为什么 Volley 以这种方式设置?

按照标准,读取 HTTP POST 方法的服务器应始终尝试以 JSON 格式(纯文本除外)读取参数,因此未完成的服务器是坏服务器?

或者,一个带有 JSON 参数的 HTTP POST 正文不是服务器通常想要的?

【讨论】:

【参考方案7】:

可能会帮助某人并节省您一些思考时间。 我有一个类似的问题,服务器代码正在寻找 Content-Type 标头。它是这样做的:

if($request->headers->content_type == 'application/json' ) //Parse JSON... 

但是 Volley 发送的标题是这样的:

'application/json; charset?utf-8'

把服务器代码改成这样就行了:

if( strpos($request->headers->content_type, 'application/json') ) //Parse JSON... 

【讨论】:

【参考方案8】:

我有类似的问题。但是我发现问题不在服务器端,而是缓存的问题。您必须清除 RequestQueue 缓存。

RequestQueue requestQueue1 = Volley.newRequestQueue(context);
requestQueue1.getCache().clear();

【讨论】:

事实证明,当您使用默认缓存实现 POST/GET 到同一资源时会发生这种情况,因为它使用 url 作为其键。见***.com/a/26331038/5922516【参考方案9】:

你可以这样做:

CustomRequest request = new CustomRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() 

        @Override
        public void onResponse(JSONObject response) 
           // Toast.makeText(SignActivity.this, response.toString(), Toast.LENGTH_SHORT).show();

            Log.d("response",""+response.toString());

            String status =  response.optString("StatusMessage");
            String actionstatus = response.optString("ActionStatus");
            Toast.makeText(SignActivity.this, ""+status, Toast.LENGTH_SHORT).show();
            if(actionstatus.equals("Success"))
            
                Intent i = new Intent(SignActivity.this, LoginActivity.class);
                startActivity(i);
                finish();
            
            dismissProgress();

        
    , new Response.ErrorListener() 
        @Override
        public void onErrorResponse(VolleyError error) 
            Toast.makeText(SignActivity.this, "Error."+error.toString(), Toast.LENGTH_SHORT).show();
            Log.d("response",""+error.toString());
            dismissProgress();
        
    ) 
        @Override
        public String getBodyContentType() 
            return "application/x-www-form-urlencoded; charset=UTF-8";
        

        @Override
        protected Map<String, String> getParams() throws AuthFailureError 
            Map<String, String> params = new HashMap<String, String>();
            params.put("Email", emailval);
            params.put("PassWord", passwordval);
            params.put("FirstName", firstnameval);
            params.put("LastName", lastnameval);
            params.put("Phone", phoneval);
            return params;
        

    ;
    AppSingleton.getInstance(SignActivity.this.getApplicationContext()).addToRequestQueue(request, REQUEST_TAG);

根据以下链接的自定义请求 Volley JsonObjectRequest Post request not working

【讨论】:

【参考方案10】:

确实有效。 我使用以下方法解析了 json 对象响应:- 像魅力一样工作。

String  tag_string_req = "string_req";
        Map<String, String> params = new HashMap<String, String>();
        params.put("user_id","CMD0005");

        JSONObject jsonObj = new JSONObject(params);
String url="" //your link
        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
                url, jsonObj, new Response.Listener<JSONObject>() 

            @Override
            public void onResponse(JSONObject response) 
                Log.d("responce", response.toString());

                try 
                    // Parsing json object response
                    // response will be a json object
                    String userbalance = response.getString("userbalance");
Log.d("userbalance",userbalance);
                    String walletbalance = response.getString("walletbalance");
                    Log.d("walletbalance",walletbalance);

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

            
        , new Response.ErrorListener() 

            @Override
            public void onErrorResponse(VolleyError error) 
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_SHORT).show();

            
        );

        AppControllerVolley.getInstance().addToRequestQueue(jsonObjReq, tag_string_req);

祝你好运! 晚安!

【讨论】:

【参考方案11】:

它对我有用,可以尝试使用 Volley 调用 Json 类型的请求和响应。

  public void callLogin(String sMethodToCall, String sUserId, String sPass) 
            RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());

            JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
                    Request.Method.POST, ConstantValues.ROOT_URL_LOCAL + sMethodToCall.toString().trim(), addJsonParams(sUserId, sPass),
    //                JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, object,
                    new Response.Listener<JSONObject>() 
                        @Override
                        public void onResponse(JSONObject response) 
                            Log.d("onResponse", response.toString());
                            Toast.makeText(VolleyMethods.this, response.toString(), Toast.LENGTH_LONG).show(); // Test

                            parseResponse(response);
    //                        msgResponse.setText(response.toString());
    //                        hideProgressDialog();
                        
                    ,
                    new Response.ErrorListener() 

                        @Override
                        public void onErrorResponse(VolleyError error) 
                            VolleyLog.d("onErrorResponse", "Error: " + error.getMessage());
                            Toast.makeText(VolleyMethods.this, error.toString(), Toast.LENGTH_LONG).show();
    //                hideProgressDialog();
                        
                    ) 

                /**
                 * Passing some request headers
                 */
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError 
                    HashMap<String, String> headers = new HashMap<String, String>();
                    headers.put("Content-Type", "application/json; charset=utf-8");
                    return headers;
                


            ;

            requestQueue.add(jsonObjectRequest);
        

        public JSONObject addJsonParams(String sUserId, String sPass) 
            JSONObject jsonobject = new JSONObject();
            try 
    //            "id":,"login":"secretary","password":"password"

                ///***//
                Log.d("addJsonParams", "addJsonParams");

    //            JSONObject jsonobject = new JSONObject();

    //            JSONObject jsonobject_one = new JSONObject();
    //
    //            jsonobject_one.put("type", "event_and_offer");
    //            jsonobject_one.put("devicetype", "I");
    //
    //            JSONObject jsonobject_TWO = new JSONObject();
    //            jsonobject_TWO.put("value", "event");
    //            JSONObject jsonobject = new JSONObject();
    //
    //            jsonobject.put("requestinfo", jsonobject_TWO);
    //            jsonobject.put("request", jsonobject_one);

                jsonobject.put("id", "");
                jsonobject.put("login", sUserId); // sUserId
                jsonobject.put("password", sPass); // sPass


    //            js.put("data", jsonobject.toString());

             catch (JSONException e) 
                e.printStackTrace();
            

            return jsonobject;
        

        public void parseResponse(JSONObject response) 

            Boolean bIsSuccess = false; // Write according to your logic this is demo.
            try 
                JSONObject jObject = new JSONObject(String.valueOf(response));
                bIsSuccess = jObject.getBoolean("success");


             catch (JSONException e) 
                e.printStackTrace();
                Toast.makeText(VolleyMethods.this, "" + e.toString(), Toast.LENGTH_LONG).show(); // Test
            

        

【讨论】:

【参考方案12】:

希望派对还不算太晚: 问题出在服务器端。如果您使用的是 PHP,请在您的 php api 文件顶部添加以下行(包含后)

$inputJSON = file_get_contents('php://input');
if(get_magic_quotes_gpc())

    $param = stripslashes($inputJSON);

else

    $param = $inputJSON;


$input = json_decode($param, TRUE);

然后检索您的值

$tag= $input['tag'];

【讨论】:

【参考方案13】:

...最初,它对我有用 ....然后突然停止工作,我没有做任何更改 代码

如果您没有对以前工作的代码进行任何更改,那么我建议检查其他参数,例如 URL ,因为如果您使用自己的计算机作为服务器,IP 地址可能会发生变化!

【讨论】:

请尝试更好地格式化您的问题。例如使用引号。

以上是关于Volley JsonObjectRequest Post 参数不再起作用的主要内容,如果未能解决你的问题,请参考以下文章

Volley JsonObjectRequest Post 参数不再起作用

Volley JsonObjectRequest Post 请求忽略参数

带有参数的 Volley jsonObjectRequest 不起作用

Android-Volley网络通信框架(StringRequest &amp; JsonObjectRequest)

Volley JsonObjectRequest Post 请求不起作用

Volley Post JsonObjectRequest 在使用 getHeader 和 getParams 时忽略参数