You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:48:14