是的,我知道很晚了,但有人可能会从中受益。
使用Retrofit2:
我昨晚从Volley迁移到Retrofit2时遇到了这个问题(正如OP所述,这是用JsonObjectRequest构建到Volley中的),尽管Jake的答案是Retrofit1.9的正确答案,但Retrofit2没有TypedString。
我的情况下需要发送一个地图<字符串,对象>,可以包含一些空值,转换为JSONObject(不会飞@FieldMap,也不特殊字符,一些得到转换),所以遵循@ b规范提示,并由Square声明:
可以使用@Body注释指定对象作为HTTP请求主体。
对象还将使用Retrofit实例上指定的转换器进行转换。如果没有添加转换器,则只能使用RequestBody。
这是一个使用RequestBody和ResponseBody的选项:
在你的接口中使用@Body和RequestBody
public interface ServiceApi
{
@POST("prefix/user/{login}")
Call<ResponseBody> login(@Path("login") String postfix, @Body RequestBody params);
}
在你的调用点创建一个RequestBody,声明它是MediaType,并使用JSONObject将你的Map转换为正确的格式:
Map<String, Object> jsonParams = new ArrayMap<>();
//put something inside the map, could be null
jsonParams.put("code", some_code);
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(new JSONObject(jsonParams)).toString());
//serviceCaller is the interface initialized with retrofit.create...
Call<ResponseBody> response = serviceCaller.login("loginpostfix", body);
response.enqueue(new Callback<ResponseBody>()
{
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
{
try
{
//get your response....
Log.d(TAG, "RetroFit2.0 :RetroGetLogin: " + rawResponse.body().string());
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable throwable)
{
// other stuff...
}
});
上面的一个优雅的Kotlin版本,允许在应用程序的其余代码中从JSON转换中抽象参数:
interface ServiceApi {
@POST("/api/login")
fun jsonLogin(@Body params: RequestBody): Deferred<LoginResult>
}
class ServiceApiUsingClass {
//ServiceApi init
fun login(username: String, password: String) =
serviceApi.jsonLogin(createJsonRequestBody(
"username" to username, "password" to password))
private fun createJsonRequestBody(vararg params: Pair<String, String>) =
RequestBody.create(
okhttp3.MediaType.parse("application/json; charset=utf-8"),
JSONObject(mapOf(*params)).toString())
}