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

Android WebService:JSON发送方法与POST响应返回规范咨询

Android WebService JSON交互最佳实践

Great question—let’s break this down into two clear parts: sending JSON data from Android, and structuring the POST response from your WebService.

1. Standard Way to Send JSON Data from Android

These days, the industry-standard tools for HTTP/JSON calls on Android are OkHttp (a lightweight, reliable HTTP client) and Retrofit (a type-safe wrapper around OkHttp that simplifies API integration). Both are maintained by Square and widely adopted for their flexibility and ease of use.

Option A: Using OkHttp (Direct, Flexible Control)

OkHttp gives you low-level control over requests, perfect if you need custom logic or edge-case handling:

// First, add OkHttp dependency to your app-level build.gradle
// implementation("com.squareup.okhttp3:okhttp:4.12.0")

// Initialize the client
val okHttpClient = OkHttpClient()

// Construct your JSON payload (or use Gson to serialize objects to strings)
val jsonPayload = """
    {
        "userId": 123,
        "action": "update_profile",
        "data": {
            "name": "John Doe",
            "email": "john@example.com"
        }
    }
""".trimIndent()

// Create request body with JSON media type
val requestBody = RequestBody.create(
    MediaType.parse("application/json; charset=utf-8"),
    jsonPayload
)

// Build the POST request
val request = Request.Builder()
    .url("https://your-webservice-endpoint.com/api/process")
    .post(requestBody)
    .addHeader("Authorization", "Bearer YOUR_AUTH_TOKEN") // Add auth headers if needed
    .build()

// Execute asynchronously (never block the main thread!)
okHttpClient.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
        // Handle network errors, timeouts, etc.
        e.printStackTrace()
        runOnUiThread { /* Update UI with error message */ }
    }

    override fun onResponse(call: Call, response: Response) {
        val responseJson = response.body?.string()
        runOnUiThread {
            if (response.isSuccessful) {
                // Parse and handle successful response
            } else {
                // Handle HTTP errors (4xx, 5xx)
                val errorDetails = response.errorBody()?.string()
            }
        }
    }
})

Option B: Using Retrofit (Type-Safe, Clean Code)

Retrofit abstracts boilerplate and uses Kotlin data classes to auto-serialize/deserialize JSON. It’s ideal for structured APIs:

// Add dependencies to build.gradle
// implementation("com.squareup.retrofit2:retrofit:2.9.0")
// implementation("com.squareup.retrofit2:converter-gson:2.9.0")

// Define data class for your request payload
data class ProfileUpdateRequest(
    val userId: Int,
    val action: String,
    val data: UserData
)

data class UserData(
    val name: String,
    val email: String
)

// Define your API interface
interface ApiClient {
    @POST("api/process")
    suspend fun updateProfile(@Body request: ProfileUpdateRequest): Response<ApiResponse>
}

// Create Retrofit instance
val retrofit = Retrofit.Builder()
    .baseUrl("https://your-webservice-endpoint.com/")
    .addConverterFactory(GsonConverterFactory.create()) // Auto-handles JSON parsing
    .build()

// Get API service instance
val apiService = retrofit.create(ApiClient::class.java)

// Make request in a coroutine (Android's recommended async pattern)
lifecycleScope.launch {
    try {
        val response = apiService.updateProfile(
            ProfileUpdateRequest(
                userId = 123,
                action = "update_profile",
                data = UserData("John Doe", "john@example.com")
            )
        )
        if (response.isSuccessful) {
            val apiResponse = response.body()
            // Handle success
        } else {
            // Handle HTTP errors
            val errorBody = response.errorBody()?.string()
        }
    } catch (e: Exception) {
        // Handle network exceptions
        e.printStackTrace()
    }
}

2. Correct Way to Structure POST Responses for Android

Between your two options, METHOD #2 is the far better choice for production apps. Here’s why:

Why METHOD #2 is Superior

  • Explicit Status Context: The Message field lets you clearly communicate request outcomes (e.g., "Good" for success, "Invalid input" for validation errors). You can even add a numeric code field (like 200 for success, 400 for bad requests) to automate error handling.
  • Clear Error Differentiation: If the request fails (e.g., missing parameters, server error), you can return a meaningful Message and set Result to null—something METHOD #1 can’t do cleanly (empty arrays could be misinterpreted as "no data" instead of "request failed").
  • Scalability: You can easily add metadata later (like pagination info: totalItems, currentPage) without breaking existing client code. METHOD #1 locks you into returning only an array, limiting future changes.

Improved Production-Ready Version of METHOD #2

For even better robustness, add a numeric status code:

{
    "code": 200,
    "message": "Request processed successfully",
    "result": [
        {
            "Field1": 1,
            "Field2": 1,
            "Field3": {
                "Field4": 1,
                "Field5": "Restaurant"
            },
            "Field6": "xyz",
            "Field7": null
        }
    ],
    "totalCount": 5 // Optional, for pagination scenarios
}

What’s Wrong with METHOD #1?

  • No Context for Failures: Clients can’t tell if an empty array means "no data exists" or "the request failed."
  • No Room for Metadata: You can’t add additional information (like error details or pagination) without breaking existing client integrations.

内容的提问来源于stack exchange,提问作者warzone_fz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:10:40