Android Volley解析错误:String无法转为JSONObject问题求助
注册请求Volley ParseError问题排查与解决
我用Android Studio和IntelliJ做移动端开发,写注册页面时,发送请求后出现错误:com.android.volley.ParseError: org.json.JSONException: Value New of type java.lang.String cannot be converted to JSONObject。但后端显示用户已经成功保存,还返回了200 OK响应,后端日志如下。我试过调整JSONObject的定义位置,问题还是没解决。
后端日志
POST "/people", parameters={} Mapped to coms309.people.PeopleController#createPerson(Person) Read "application/json;charset=utf-8" to [5 dave borucki dave@mail.com dunk] 5 dave borucki dave@mail.com dunk Using 'text/plain', given [*/*] and supported [text/plain, */*, application/json, application/*+json] Writing ["New person dave Saved"] Completed 200 OK
前端代码
package com.example.androidexample; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.android.volley.RequestQueue; import com.android.volley.toolbox.Volley; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; public class SignupActivity extends AppCompatActivity { private EditText firstNameEditText; private EditText lastNameEditText; private EditText emailAddressEditText; private EditText passwordEditText; private Button signupButton; private Button loginButton; private JSONObject user; private static final String URL_SIGNUP = "http://10.0.2.2:8081/people"; private EditText errorEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_signup); /* initialize UI elements */ firstNameEditText = findViewById(R.id.signup_firstName_edt); // link to username edtext in the Signup activity XML lastNameEditText = findViewById(R.id.signup_lastName_edt); // link to password edtext in the Signup activity XML emailAddressEditText = findViewById(R.id.signup_email_edt); // link to confirm edtext in the Signup activity XML passwordEditText = findViewById(R.id.signup_password_edt); // link to login button in the Signup activity XML signupButton = findViewById(R.id.signup_signup_btn); // link to signup button in the Signup activity XML loginButton = findViewById(R.id.signup_login_btn); errorEditText = findViewById(R.id.errorText); /* click listener on login button pressed */ loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* when login button is pressed, use intent to switch to Login Activity */ Intent intent = new Intent(SignupActivity.this, LoginActivity.class); startActivity(intent); // go to LoginActivity } }); /* click listener on signup button pressed */ signupButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* grab strings from user inputs */ String firstName = firstNameEditText.getText().toString(); String lastName = lastNameEditText.getText().toString(); String emailAddress = emailAddressEditText.getText().toString(); String password = passwordEditText.getText().toString(); System.out.println("Signup pressed"); user = new JSONObject(); try { user.put("id", 5); user.put("firstName", firstName); user.put("lastName", lastName); user.put("emailAddress", emailAddress); user.put("password", password); } catch (JSONException e) { throw new RuntimeException(e); } signUpRequest(); } }); } private void signUpRequest() { RequestQueue queue = Volley.newRequestQueue(this); JsonObjectRequest request = new JsonObjectRequest( Request.Method.POST, URL_SIGNUP, user, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Toast.makeText(getApplicationContext(),"Account Created", Toast.LENGTH_LONG).show(); Intent successIntent = new Intent(SignupActivity.this, MainActivity.class); //successIntent.putExtra("id", id); startActivity(successIntent); } },new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), "Signup unsuccessful (VolleyError)", Toast.LENGTH_LONG).show(); errorEditText.setText(error.toString()); } }); queue.add(request); } }
问题原因&解决方案
问题根因
从后端日志能明确看到,接口返回的是文本格式内容:["New person dave Saved"],但前端使用的JsonObjectRequest默认要求后端返回标准JSONObject格式,Volley在尝试把文本响应解析成JSONObject时,自然会抛出转换异常。
两种修复方式
方式一:修改前端请求类型(推荐)
把JsonObjectRequest替换为StringRequest,适配后端返回的字符串格式,同时保留JSON请求体的发送:
private void signUpRequest() { RequestQueue queue = Volley.newRequestQueue(this); StringRequest request = new StringRequest( Request.Method.POST, URL_SIGNUP, new Response.Listener<String>() { @Override public void onResponse(String response) { Toast.makeText(getApplicationContext(),"Account Created", Toast.LENGTH_LONG).show(); Intent successIntent = new Intent(SignupActivity.this, MainActivity.class); startActivity(successIntent); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), "Signup unsuccessful (VolleyError)", Toast.LENGTH_LONG).show(); errorEditText.setText(error.toString()); } }) { // 重写getBody,发送JSON格式的请求体 @Override public byte[] getBody() throws AuthFailureError { try { return user.toString().getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } // 设置请求头,告知后端请求体为JSON格式 @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json; charset=utf-8"); return headers; } }; queue.add(request); }
方式二:修改后端返回格式
让后端返回标准的JSONObject格式,例如:
{"message": "New person dave Saved"}
这种情况下前端无需修改代码,JsonObjectRequest就能正常解析响应。
内容的提问来源于stack exchange,提问作者Dave Borucki
相关产品推荐
相关产品推荐

