【问题标题】:Retrofit POST with jsonObject not uploading使用 jsonObject 改造 POST 不上传
【发布时间】:2020-10-31 12:34:54
【问题描述】:

我已经为此工作了几个小时,但没有取得任何进展。我是改装新手,基本上只是尝试使用 jsonObject 发出简单的发布请求,但收到此错误:

java.lang.illegalStateException: Expected BEGIN_OBJECT but was STRING at line 
1 column 1 path $

我已经尝试将客户端代码的每一部分更改为使用 multipart 或 requestBody 甚至我的 php 代码,但没有任何效果,还尝试在脚本中回显输入,但它打印为空。非常感谢任何和每一个回复,谢谢。

界面

interface ApiInterface {
    @Headers("Content-Type: application/json")
    @POST(BuildConfig.URL_REGISTER)
    fun signUpUser(@Body jsonObject: JSONObject): Call<Response>
}

回应

data class Response(@SerializedName("success") val success: Boolean,
    @SerializedName("message") val message: String,
    @SerializedName("userId") val userId:String)

客户

class ApiClient {

private external fun register(): String

companion object {
    // Used to load the 'native-lib' library on application startup.
    init {
        System.loadLibrary("native-lib")
    }
}

private val okhttpClient = OkHttpClient.Builder().build()

private val gson: Gson = GsonBuilder()
    .setLenient()
    .create()

val instance: ApiInterface by lazy {
    val  retrofit = Retrofit.Builder()
        .baseUrl(register())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .client(okhttpClient)
        .build()
    retrofit.create(ApiInterface::class.java)
}

请求

val jsonObject = JSONObject()
    jsonObject.put("username", username)
    jsonObject.put("password", password)
    jsonObject.put("email", email)
    jsonObject.put("termsOfService", termsOfService)
    jsonObject.put("profilePicPath", imagePath)

ApiClient().instance.signUpUser(jsonObject).enqueue(object: Callback<com.passionit.picnbuy.models.Response>{
    override fun onFailure(
        call: Call<com.passionit.picnbuy.models.Response>, t: Throwable) {
            Toast.makeText(this@LoginOrSignUpActivity, t.message, Toast.LENGTH_LONG).show()
        }

    override fun onResponse(call: Call<com.passionit.picnbuy.models.Response>, response: Response<com.passionit.picnbuy.models.Response>) {
        Toast.makeText(this@LoginOrSignUpActivity, response.message(), Toast.LENGTH_LONG).show()
        if (response.body()!!.success) { //success, now uploading pfp
            //successful response doing stuff...
        } else { 
            //error caught in script file
        }
    }

})

PHP 文件

<?php
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);

$conn = new mysqli("localhost", "root", "", "database");

if ($conn->connect_error) {
    die("Failed to connect: " . $conn->connect_error);
}

$username = $input["username"];
$password = $input["password"];
$email = $input["email"];
$termsOfService = $input["termsOfService"];
$profilePicPath = $input["profilePicPath"];

//converting data
$termsOfService = $termsOfService ? 'true' : 'false';

//Username check
$usernameCheckQuery = $conn->prepare("SELECT * FROM allUsers WHERE username = ?");
$usernameCheckQuery->bind_param("s", $username);
$usernameCheckQuery->execute(); 

if ($usernameCheckQuery->num_rows > 0) {//username exists
    $usernameCheckQuery->close();

    print(json_encode(array('success' => false, 'message' => "username already exists")));

} else {
    $usernameCheckQuery->close();

    password_hash($password, PASSWORD_DEFAULT);
    $query = $conn->prepare("INSERT INTO allUsers(username, password, email, tOS, pfPPath) 
        VALUES(?, ?, ?, ?, ?)");
    $query->bind_param("sssss", $username, $password, $email, $termsOfService, $profilePicPath);
    $query->execute();
    $query->close();
    print(json_encode(array('success' => true)));
}

$conn->close();
json_last_error();
?>

【问题讨论】:

    标签: php android kotlin retrofit


    【解决方案1】:

    亲爱的朋友。 我建议将以下两行添加到 build.gradle 文件中。

        // Logging Interceptor
        implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
        implementation 'org.conscrypt:conscrypt-android:2.4.0'
    

    并如下图使用

    
    object ApiServiceContainer {
        private var apiService: ApiService? = null
        fun getApiService(): ApiService {
            if (apiService == null) {
                val logging = HttpLoggingInterceptor()
                logging.level = HttpLoggingInterceptor.Level.BODY
                val httpClient = OkHttpClient.Builder()
                httpClient.addInterceptor { chain ->
                    val original = chain.request()
                    val requestBuilder = original.newBuilder()
                        .header("Authorization", "Bearer " + token)
                        .header("Accept", "application/json")
                        .header("Content-Type", "application/json")
                    val request = requestBuilder.build()
                    chain.proceed(request)
                }
                httpClient.connectTimeout(30, TimeUnit.SECONDS)
                httpClient.readTimeout(30, TimeUnit.SECONDS)
                httpClient.addNetworkInterceptor(logging)
                val okHttpClient = httpClient.build()
                val gson = GsonBuilder()
                    .setLenient()
                    .create()
                val retrofit = Retrofit.Builder()
                    .baseUrl(EndPoints.API_BASE_URL)
                    .addConverterFactory(
                        GsonConverterFactory.create(gson)
                    )
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(okHttpClient)
                    .build()
                apiService = retrofit.create(ApiService::class.java)
            }
            return apiService!!
        }
    
    

    所以你可以看到服务器发出的错误。

    【讨论】:

    • 谢谢我不知道这个,我最终找到了另一个解决方案。
    【解决方案2】:

    我发现无论出于何种原因,在 php 中接收到除了数组或字段之外的任何内容都会添加额外的字符,我最终只是使用了这样的字段。

    interface ApiInterface {
    @FormUrlEncoded
    @POST(BuildConfig.URL_REGISTER)
    fun signUpUser(@Field("username") username: String,
                   @Field("password") password: String,
                   @Field("email") email: String,
                   @Field("termsOfService") termsOfService: Boolean,
                   @Field("profilePicPath") profilePicPath: String): Call<Response>
    

    }

    在 php 中它是这样接收的

    $username = $_POST['username'];
    $password = $_POST['password'];
    $email = $_POST['email'];
    $termsOfService = $_POST['termsOfService'];
    $profilePicPath = $_POST['profilePicPath'];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-16
      • 2015-09-16
      • 1970-01-01
      • 2020-01-06
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 2016-04-28
      相关资源
      最近更新 更多