这个问题以前可能被问过,但没有明确的答案。如何在Retrofit请求的主体中发布原始的整个JSON ?
在这里看到类似的问题。或者这个答案是正确的,它必须是表单url编码并作为一个字段传递?我真的希望不是,因为我要连接的服务只是希望在文章正文中有原始JSON。它们不是用来为JSON数据寻找特定字段的。
I just want to clarify this with the restperts once and for all. One person answered not to use Retrofit. The other was not certain of the syntax. Another thinks yes it can be done but only if its form url-encoded and placed in a field (that's not acceptable in my case). No, I can't re-code all the services for my Android client. And yes, it's very common in major projects to post raw JSON instead of passing over JSON content as field property values. Let's get it right and move on. Can someone point to the documentation or example that shows how this is done? Or provide a valid reason why it can/should not be done.
更新:有一件事我可以百分之百确定。你可以在谷歌的Volley中做到这一点。这是与生俱来的。我们可以在Retrofit中这样做吗?
我发现当你使用一个复合对象作为@Body参数时,它不能很好地与Retrofit的GSONConverter一起工作(假设你正在使用它)。
你必须使用JsonObject,而不是JsonObject,它添加了NameValueParams而没有详细说明它-你只能看到如果你添加了日志拦截器的另一个依赖项,和其他诡计。
所以我发现解决这个问题的最佳方法是使用RequestBody。
您可以通过一个简单的api调用将对象转换为RequestBody并启动它。
在我的情况下,我转换一个地图:
val map = HashMap<String, Any>()
map["orderType"] = orderType
map["optionType"] = optionType
map["baseAmount"] = baseAmount.toString()
map["openSpotRate"] = openSpotRate.toString()
map["premiumAmount"] = premiumAmount.toString()
map["premiumAmountAbc"] = premiumAmountAbc.toString()
map["conversionSpotRate"] = (premiumAmountAbc / premiumAmount).toString()
return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONObject(map).toString())
这就是号召:
@POST("openUsvDeal")
fun openUsvDeal(
@Body params: RequestBody,
@Query("timestamp") timeStamp: Long,
@Query("appid") appid: String = Constants.APP_ID,
): Call<JsonObject>
为了更清楚地说明这里给出的答案,下面是如何使用扩展函数。这仅适用于使用Kotlin的情况
如果你正在使用com.squareup.okhttp3:okhttp:4.0.1,旧的创建MediaType和RequestBody对象的方法已经被弃用,不能在Kotlin中使用。
如果您希望使用扩展函数从字符串中获取MediaType对象和ResponseBody对象,首先将以下行添加到您希望在其中使用它们的类中。
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
现在可以通过这种方式直接获取MediaType对象
val mediaType = "application/json; charset=utf-8".toMediaType()
要获得RequestBody的对象,首先要将您想要发送的JSONObject转换为字符串。您必须将mediaType对象传递给它。
val requestBody = myJSONObject.toString().toRequestBody(mediaType)
我想比较排射的速度和改装的发送和接收数据,我写在下面的代码(改装部分)
第一个依赖:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
}
然后界面:
public interface IHttpRequest {
String BaseUrl="https://example.com/api/";
@POST("NewContract")
Call<JsonElement> register(@Body HashMap registerApiPayload);
}
和一个函数来设置参数,张贴数据到服务器(在MainActivity):
private void Retrofit(){
Retrofit retrofitRequest = new Retrofit.Builder()
.baseUrl(IHttpRequest.BaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
// set data to send
HashMap<String,String> SendData =new HashMap<>();
SendData.put("token","XYXIUNJHJHJHGJHGJHGRTYTRY");
SendData.put("contract_type","0");
SendData.put("StopLess","37000");
SendData.put("StopProfit","48000");
final IHttpRequest request=retrofitRequest.create(IHttpRequest.class);
request.register(SendData).enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
if (response.isSuccessful()){
Toast.makeText(getApplicationContext(),response.body().toString(),Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<JsonElement> call, Throwable t) {
}
});
}
对我来说,改装比截击更快。
火通话
@Headers("Content-Type: application/json")
@POST("/set_data")
Call<CommonResponse> setPreferences(@Body RequestData request);
注意:使用Retrofit的GSON库
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class RequestData {
@SerializedName("access_token")
@Expose
private String accessToken;
@SerializedName("data")
@Expose
private Data data;
// The above 'Data' is another similar class to add inner JSON objects. JSONObject within a JSONObject.
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public void setData(Data data) {
this.data = data;
}
}
我想这将有所帮助,您可能已经拥有了所有集成,我们不需要任何花哨的东西来使用上面的代码片段。它非常适合我。
这是我在当前版本的2.6.2中工作的地方,
首先,我们需要添加一个Scalars Converter到我们的Gradle依赖项列表中,它负责将java.lang.String对象转换为文本/纯请求体,
implementation'com.squareup.retrofit2:converter-scalars:2.6.2'
然后,我们需要将一个转换器工厂传递给我们的Retrofit构建器。它稍后将告诉Retrofit如何转换传递给服务的@Body参数。
private val retrofitBuilder: Retrofit.Builder by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
}
注:在我的改造建设者我有两个转换器Gson和
标量,你可以使用他们,但发送Json的主体,我们需要
focus Scalars,所以如果你不需要Gson删除它
然后用String体参数对服务进行翻新。
@Headers("Content-Type: application/json")
@POST("users")
fun saveUser(@Body user: String): Response<MyResponse>
然后创建JSON主体
val user = JsonObject()
user.addProperty("id", 001)
user.addProperty("name", "Name")
呼叫您的服务
RetrofitService.myApi.saveUser(user.toString())