【问题标题】:How to POST raw whole JSON in the body of a Retrofit request?如何在改造请求的正文中发布原始的整个 JSON?
【发布时间】:2014-02-19 08:07:38
【问题描述】:

这个问题之前可能已经被问过,但没有得到明确的回答。究竟如何在 Retrofit 请求的正文中发布原始的整个 JSON?

查看类似问题here。或者这个答案是否正确,它must be form url encoded and passed as a field?我真的不希望这样,因为我连接的服务只是在帖子正文中期待原始 JSON。它们未设置为查找 JSON 数据的特定字段。

我只想用 restperts 一劳永逸地澄清这一点。一个人回答不要使用 Retrofit。另一个不确定语法。另一个人认为是的,它可以做到,但前提是它的形式是 url 编码并放在一个字段中(这在我的情况下是不可接受的)。不,我无法为我的 Android 客户端重新编码所有服务。是的,在主要项目中发布原始 JSON 而不是将 JSON 内容作为字段属性值传递是很常见的。让我们做对并继续前进。有人可以指出显示这是如何完成的文档或示例吗?或者提供一个可以/不应该做的正当理由。

更新:我可以 100% 确定地说一件事。您可以在 Google 的 Volley 中执行此操作。它是内置的。我们可以在 Retrofit 中做到这一点吗?

【问题讨论】:

  • 杰克沃顿的帖子是正确的!标记为答案!
  • 你可能会更好地使用jsonObject。
  • 像这样与RequestBody完美配合->RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);详细回答futurestud.io/tutorials/…

标签: android rest http-post retrofit android-json


【解决方案1】:

@Body 注解定义了一个请求体。

interface Foo {
  @POST("/jayson")
  FooResponse postJson(@Body FooRequest body);
}

由于 Retrofit 默认使用 Gson,FooRequest 实例将被序列化为 JSON 作为请求的唯一主体。

public class FooRequest {
  final String foo;
  final String bar;

  FooRequest(String foo, String bar) {
    this.foo = foo;
    this.bar = bar;
  }
}

调用方式:

FooResponse = foo.postJson(new FooRequest("kit", "kat"));

将产生以下正文:

{"foo":"kit","bar":"kat"}

Gson docs 有更多关于对象序列化如何工作的信息。

现在,如果您真的想自己发送“原始”JSON 作为正文(但请使用 Gson!),您仍然可以使用 TypedInput

interface Foo {
  @POST("/jayson")
  FooResponse postRawJson(@Body TypedInput body);
}

TypedInput 被定义为“具有关联 MIME 类型的二进制数据”。有两种方法可以通过上述声明轻松发送原始数据:

  1. 使用TypedByteArray 发送原始字节和 JSON mime 类型:

    String json = "{\"foo\":\"kit\",\"bar\":\"kat\"}";
    TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
    FooResponse response = foo.postRawJson(in);
    
  2. 子类TypedString 以创建TypedJsonString 类:

    public class TypedJsonString extends TypedString {
      public TypedJsonString(String body) {
        super(body);
      }
    
      @Override public String mimeType() {
        return "application/json";
      }
    }
    

    然后使用类似于 #1 的该类的实例。

【讨论】:

  • 很好,但是,有没有办法在不制作pojos的情况下制作这个?
  • 这不适用于改造 2。TypedInput 和 TypedString 类已被删除。
  • @jakewharton TypedString 已被删除,我们能做什么?
  • 对于Retrofit2,你可以使用RequestBody创建一个raw body。
  • 我收到了这个异常java.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
【解决方案2】:

是的,我知道现在已经晚了,但有人可能会从中受益。

使用 Retrofit2:

我昨晚从 Volley 迁移到 Retrofit2 时遇到了这个问题(正如 OP 所说,这是通过 JsonObjectRequest 直接内置到 Volley 中的),尽管 Jake 的答案是 Retrofit1.9 的正确答案,Retrofit2 没有TypedString

我的案例需要发送一个Map<String,Object>,它可能包含一些空值,转换为 JSONObject(不会与@FieldMap 一起飞行,特殊字符也不会,有些会被转换),所以遵循@bnorms 提示,并且如Square所述:

可以使用@Body 注释指定一个对象用作HTTP 请求正文。

对象也将使用 Retrofit 实例上指定的转换器进行转换。如果不添加转换器,则只能使用 RequestBody。

所以这是一个使用RequestBodyResponseBody 的选项:

在您的界面中使用@BodyRequestBody

public interface ServiceApi
{
    @POST("prefix/user/{login}")
    Call<ResponseBody> login(@Path("login") String postfix, @Body RequestBody params);  
}

在您的调用点创建一个RequestBody,说明它是 MediaType,并使用 JSONObject 将您的地图转换为正确的格式:

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())
}

【讨论】:

  • 是的,我看到很多复杂的回应。如果你正在使用 Retrofit2 并想做凌空抽射的JsonObjectRequest,你需要做的就是这个。很好的答案。
  • Retrofit 在所有 json 对象的顶部添加了一个名为“nameValuePairs”的键。我怎样才能删除这个@TommySM
  • 谢谢!这解决了我的问题。现在我可以直接发送 JSONObject 而无需创建 POJO。
  • 这是帮助我 post a null value 到 requestBody 中的属性的唯一解决方案,否则会被忽略。
  • 嘿@hushed_voice 我知道我迟到了,但我遇到了同样的问题并通过将没有注释的函数移出界面来解决它。我编辑了帖子以便于理解。
【解决方案3】:

我们也可以直接使用HashMap&lt;String, Object&gt;来代替classes来发送body参数 例如

interface Foo {
  @POST("/jayson")
  FooResponse postJson(@Body HashMap<String, Object> body);
}

【讨论】:

  • 那时你可以像HashMap那样创建Hash map,可以创建有点复杂的数组和对象JSON。
  • 如果您不想被绑定到某种 POJO,这非常好。
  • @Nil 你不能使用改造来发送 json 对象......你坚持 pojo 或我的回答......这是改造的本质。如果你想了解更多关于这个的问题,请询问 Jake Wharton,他是改造开发人员伙计,他的答案也可以通过 pojo 获得。
  • 我收到了 IllegalArgumentException: Unable to create @Body converter for java.util.HashMap&lt;java.lang.String, java.lang.Object&gt; 和 Moshi。我认为这个工作需要 Gson
  • 如果使用 Kotlin,请使用 的 hashmap
【解决方案4】:

Retrofit2 中,当您想以原始格式发送参数时,您必须使用 Scalars

首先在你的 gradle 中添加这个:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

您的界面

public interface ApiInterface {

    String URL_BASE = "http://10.157.102.22/rest/";

    @Headers("Content-Type: application/json")
    @POST("login")
    Call<User> getUser(@Body String body);

}

活动

   public class SampleActivity extends AppCompatActivity implements Callback<User> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.URL_BASE)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);


        // prepare call in Retrofit 2.0
        try {
            JSONObject paramObject = new JSONObject();
            paramObject.put("email", "sample@gmail.com");
            paramObject.put("pass", "4384984938943");

            Call<User> userCall = apiInterface.getUser(paramObject.toString());
            userCall.enqueue(this);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onResponse(Call<User> call, Response<User> response) {
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
    }
}

【讨论】:

  • 这里的技巧是Gson之前的Scalar适配器,否则Gson会将你手动序列化的JSON包装在一个String中。
  • jonathan-nolasco-barrientos 你必须将 .baseUrl(ApiInterface.ENDPOINT) 更改为 .baseUrl(ApiInterface.URL_BASE )
  • 当您使用GsonConverterFactory 时,.toString() 不是必需的。您可以使用JsonObject 而不是JSONObject 声明Call&lt;User&gt; getUser(@Body JsonObject body);,并直接传递paramObject。它会工作得很好。
  • @IgordeLorenzi 解决了我的问题,因为我使用 spring boot 从 gson 中检索 json 仅 JsonObject 工作正常
  • @IgordeLorenzi 与标量一起使用 JSONObject 或 JsonObject 有区别吗?
【解决方案5】:

使用JsonObject 就是这样:

  1. 像这样创建你的界面:

    public interface laInterfaz{ 
        @POST("/bleh/blah/org")
        void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback);
    }
    
  2. 根据jsons结构制作JsonObject。

    JsonObject obj = new JsonObject();
    JsonObject payerReg = new JsonObject();
    payerReg.addProperty("crc","aas22");
    payerReg.addProperty("payerDevManufacturer","Samsung");
    obj.add("payerReg",payerReg);
    /*json/*
        {"payerReg":{"crc":"aas22","payerDevManufacturer":"Samsung"}}
    /*json*/
    
  3. 调用服务:

    service.registerPayer(obj, callBackRegistraPagador);
    
    Callback<JsonObject> callBackRegistraPagador = new Callback<JsonObject>(){
        public void success(JsonObject object, Response response){
            System.out.println(object.toString());
        }
    
        public void failure(RetrofitError retrofitError){
            System.out.println(retrofitError.toString());
        }
    };
    

那就是它!在我个人看来,它比制作 pojos 和处理课堂混乱要好得多。这样干净多了。

【讨论】:

  • 如果我不想在 jsonobject 类中发送特定值怎么办。我可以在上面使用哪个注释?
  • 如上例所示... JsonObject 因为它是一个对象,所以不使用任何注释。在您的情况下,如果您不想发送特定值,则可能只是不将其添加为属性...
  • 我的意思是我不想发送在类中声明的值。顺便说一句,我解决了这个问题。有一个名称是公开的注释。
  • 这是最灵活的方式。即使您不知道您将拥有多少个字段,或者即使您不知道他们从我这里命名为 +1,您也可以构建您的 json 对象
  • 我收到错误服务方法不能返回 void。对于方法 APIServices.signUpUser
【解决方案6】:

我特别喜欢 Jake 对 TypedString 子类 above 的建议。您确实可以根据您计划推送的各种 POST 数据创建各种子类,每个子类都有自己自定义的一组一致的调整。

您还可以选择在 Retrofit API 中为 JSON POST 方法添加标头注释……

@Headers( "Content-Type: application/json" )
@POST("/json/foo/bar/")
Response fubar( @Body TypedString sJsonBody ) ;

…但是使用子类更明显是自记录的。

@POST("/json/foo/bar")
Response fubar( @Body TypedJsonString jsonBody ) ;

【讨论】:

  • 通过使用 JW 建议中的 TypedJsonString 的清晰示例节省了一天
【解决方案7】:

1)添加依赖-

 compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

2) 制作 Api Handler 类

    public class ApiHandler {


  public static final String BASE_URL = "URL";  

    private static Webservices apiService;

    public static Webservices getApiService() {

        if (apiService == null) {

           Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();
            Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(BASE_URL).build();

            apiService = retrofit.create(Webservices.class);
            return apiService;
        } else {
            return apiService;
        }
    }


}

3)从 Json 模式 2 pojo 制作 bean 类

记住
-目标语言:Java -源类型:JSON - 注释风格:Gson -select 包括getter和setter - 您也可以选择允许其他属性

http://www.jsonschema2pojo.org/

4)为api调用制作接口

    public interface Webservices {

@POST("ApiUrlpath")
    Call<ResponseBean> ApiName(@Body JsonObject jsonBody);

}

如果您有表单数据参数,请添加以下行

@Headers("Content-Type: application/x-www-form-urlencoded")

表单数据参数的其他方式检查这个link

5)制作JsonObject作为参数传入body

 private JsonObject ApiJsonMap() {

    JsonObject gsonObject = new JsonObject();
    try {
        JSONObject jsonObj_ = new JSONObject();
        jsonObj_.put("key", "value");
        jsonObj_.put("key", "value");
        jsonObj_.put("key", "value");


        JsonParser jsonParser = new JsonParser();
        gsonObject = (JsonObject) jsonParser.parse(jsonObj_.toString());

        //print parameter
        Log.e("MY gson.JSON:  ", "AS PARAMETER  " + gsonObject);

    } catch (JSONException e) {
        e.printStackTrace();
    }

    return gsonObject;
}

6) 像这样调用 API

private void ApiCallMethod() {
    try {
        if (CommonUtils.isConnectingToInternet(MyActivity.this)) {
            final ProgressDialog dialog;
            dialog = new ProgressDialog(MyActivity.this);
            dialog.setMessage("Loading...");
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

            Call<ResponseBean> registerCall = ApiHandler.getApiService().ApiName(ApiJsonMap());
            registerCall.enqueue(new retrofit2.Callback<ResponseBean>() {
                @Override
                public void onResponse(Call<ResponseBean> registerCall, retrofit2.Response<ResponseBean> response) {

                    try {
                        //print respone
                        Log.e(" Full json gson => ", new Gson().toJson(response));
                        JSONObject jsonObj = new JSONObject(new Gson().toJson(response).toString());
                        Log.e(" responce => ", jsonObj.getJSONObject("body").toString());

                        if (response.isSuccessful()) {

                            dialog.dismiss();
                            int success = response.body().getSuccess();
                            if (success == 1) {



                            } else if (success == 0) {



                            }  
                        } else {
                            dialog.dismiss();


                        }


                    } catch (Exception e) {
                        e.printStackTrace();
                        try {
                            Log.e("Tag", "error=" + e.toString());

                            dialog.dismiss();
                        } catch (Resources.NotFoundException e1) {
                            e1.printStackTrace();
                        }

                    }
                }

                @Override
                public void onFailure(Call<ResponseBean> call, Throwable t) {
                    try {
                        Log.e("Tag", "error" + t.toString());

                        dialog.dismiss();
                    } catch (Resources.NotFoundException e) {
                        e.printStackTrace();
                    }
                }

            });

        } else {
            Log.e("Tag", "error= Alert no internet");


        }
    } catch (Resources.NotFoundException e) {
        e.printStackTrace();
    }
}

【讨论】:

    【解决方案8】:

    添加 ScalarsConverterFactory 进行改造:

    在毕业典礼中:

    implementation'com.squareup.retrofit2:converter-scalars:2.5.0'
    

    您的改造:

    retrofit = new Retrofit.Builder()
                .baseUrl(WEB_DOMAIN_MAIN)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    

    把你的调用接口@Body参数改成String,别忘了加上@Headers("Content-Type: application/json")

    @Headers("Content-Type: application/json")
    @POST("/api/getUsers")
    Call<List<Users>> getUsers(@Body String rawJsonString);
    

    现在您可以发布原始 json。

    【讨论】:

    • 它有效!!你拯救了我的一天!我也在使用 moshi 和 ScalarsConverterFactory。到目前为止没有问题。
    【解决方案9】:

    我发现当您将复合对象用作@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>
    

    【讨论】:

    • 在谷歌上搜索了一夜之后,这对我有帮助。
    【解决方案10】:

    这对我当前版本的retrofit 有用2.6.2

    首先,我们需要在 Gradle 依赖项列表中添加一个 Scalars Converter,它负责将 java.lang.String 对象转换为 text/plain 请求正文,

    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())
    }
    

    注意:在我的改造构建器中,我有两个转换器 GsonScalars 您可以同时使用它们,但是要发送 Json 正文,我们需要 关注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())
    

    【讨论】:

      【解决方案11】:

      如果您不想为每个 API 调用创建 pojo 类,可以使用 hashmap。

      HashMap<String,String> hashMap=new HashMap<>();
              hashMap.put("email","this@gmail.com");
              hashMap.put("password","1234");
      

      然后像这样发送

      Call<JsonElement> register(@Body HashMap registerApiPayload);
      

      【讨论】:

        【解决方案12】:

        使用以下发送json

        final JSONObject jsonBody = new JSONObject();
            try {
        
                jsonBody.put("key", "value");
        
            } catch (JSONException e){
                e.printStackTrace();
            }
            RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(jsonBody).toString());
        

        并将其传递给 url

        @Body RequestBody key
        

        【讨论】:

          【解决方案13】:

          如果您不想创建额外的类或使用JSONObject,您可以使用HashMap

          改造界面:

          @POST("/rest/registration/register")
          fun signUp(@Body params: HashMap<String, String>): Call<ResponseBody>
          

          呼叫:

          val map = hashMapOf(
              "username" to username,
              "password" to password,
              "firstName" to firstName,
              "surname" to lastName
          )
          
          retrofit.create(TheApi::class.java)
               .signUp(map)
               .enqueue(callback)
          

          【讨论】:

            【解决方案14】:

            在 Retrofit 中发送原始 json 所需的东西。

            1) 确保添加以下标题并删除任何其他重复的标题。因为,在 Retrofit 的官方documentation 上,他们特别提到-

            请注意,标题不会相互覆盖。所有标题都带有 请求中将包含相同的名称。

            @Headers({"Content-Type: application/json"})
            

            2) a. 如果您使用转换器工厂,您可以将 json 作为 String、JSONObject、JsonObject 甚至 POJO 传递。还检查过,ScalarConverterFactory 不是必需的,只有 GsonConverterFactory 可以完成这项工作。

            @POST("/urlPath")
            @FormUrlEncoded
            Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key, 
                                 @Body JsonObject/POJO/String requestBody);
            

            2) b.如果您没有使用任何转换器工厂,那么您必须使用 okhttp3 的 RequestBody,因为 Retrofit 的文档说-

            对象也将使用指定的转换器进行转换 改造实例。如果不加转换器,则只能是RequestBody 用过。

            RequestBody requestBody=RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonString);
            
            @POST("/urlPath")
            @FormUrlEncoded
            Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key, 
                             @Body RequestBody requestBody);
            

            3)成功!!

            【讨论】:

            • 预期为字符串,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT
            • @AhamadullahSaikat 您的 gson 试图解析的 json 字符串与提供给它的 pojo 的结构不同。
            • @DarshanMiskin 谢谢你对我的帮助
            【解决方案15】:

            经过这么多努力,发现基本的区别是您需要发送JsonObject而不是JSONObject作为参数。

            【讨论】:

            • 我也犯了同样的错误:p
            【解决方案16】:

            基于最佳答案,我有一个不必为每个请求都创建 POJO 的解决方案。

            例如,我想发布这个 JSON。

            {
                "data" : {
                    "mobile" : "qwer",
                    "password" : "qwer"
                },
                "commom" : {}
            }
            

            然后,我创建一个这样的通用类:

            import java.util.Map;
            import java.util.HashMap;
            
            public class WRequest {
            
                Map<String, Object> data;
                Map<String, Object> common;
            
                public WRequest() {
                    data = new HashMap<>();
                    common = new HashMap<>();
                }
            }
            

            最后,当我需要一个 json 时

            WRequest request = new WRequest();
            request.data.put("type", type);
            request.data.put("page", page);
            

            标有注解@Body的请求然后可以传递给Retrofit。

            【讨论】:

              【解决方案17】:

              你需要在界面中设置@Body

              @Headers({ "Content-Type: application/json;charset=UTF-8"})
                  @POST("Auth/Login")
                  Call<ApiResponse> loginWithPhone(@Body HashMap<String, String> fields);
              

              要通过原始主体进行改造,只需使用:

               HashMap<String,String> SendData =new HashMap<>();
                      SendData.put("countryCode",ccode);
                      SendData.put("phoneNumber",phone);
              
                      Call<ApiResponse>call = serviceInterface.loginWithPhone(SendData);
              

              这对我有用:

              【讨论】:

                【解决方案18】:

                为了更清楚地了解此处给出的答案,这是您可以使用扩展功能的方式。 这仅适用于您使用 Kotlin

                如果您使用 com.squareup.okhttp3:okhttp:4.0.1,创建 MediaTypeRequestBody 对象的旧方法已被弃用,无法在 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)
                

                【讨论】:

                  【解决方案19】:

                  根据 TommySM 的回答解决了我的问题(见上)。 但我不需要登录,我使用 Retrofit2 来测试 https GraphQL API,如下所示:

                  1. 在 json 注释的帮助下定义了我的 BaseResponse 类(导入 jackson.annotation.JsonProperty)。

                    public class MyRequest {
                        @JsonProperty("query")
                        private String query;
                    
                        @JsonProperty("operationName")
                        private String operationName;
                    
                        @JsonProperty("variables")
                        private String variables;
                    
                        public void setQuery(String query) {
                            this.query = query;
                        }
                    
                        public void setOperationName(String operationName) {
                            this.operationName = operationName;
                        }
                    
                        public void setVariables(String variables) {
                            this.variables = variables;
                        }
                    }
                    
                  2. 在接口中定义调用过程:

                    @POST("/api/apiname")
                    Call<BaseResponse> apicall(@Body RequestBody params);
                    
                  3. 在测试体中调用 apicall: 创建一个 MyRequest 类型的变量(例如“myLittleRequest”)。

                    Map<String, Object> jsonParams = convertObjectToMap(myLittleRequest);
                    RequestBody body = 
                         RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
                                        (new JSONObject(jsonParams)).toString());
                    response = hereIsYourInterfaceName().apicall(body).execute();
                    

                  【讨论】:

                    【解决方案20】:

                    我想比较截击和改造的速度,以发送和接收我在下面的代码中编写的数据(改造部分)

                    第一个依赖:

                    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) {
                    
                            }
                        });
                    
                    }
                    

                    在我的情况下,我发现 Retrofit 比 volley 更快。

                    【讨论】:

                      【解决方案21】:

                      API 调用

                      @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;
                          }
                      }
                      

                      我想这会有所帮助,剩下你可能已经拥有的所有集成,我们不需要任何花哨的东西来使用上面的代码 sn-p。它对我来说非常有效。

                      【讨论】:

                        【解决方案22】:

                        我试过这个: 在创建 Retrofit 实例时,将此转换器工厂添加到改造构建器中:

                        gsonBuilder = new GsonBuilder().serializeNulls()     
                        your_retrofit_instance = Retrofit.Builder().addConverterFactory( GsonConverterFactory.create( gsonBuilder.create() ) )
                        

                        【讨论】:

                          【解决方案23】:

                          在创建时 OkHttpClient 将用于改造。

                          像这样添加一个拦截器。

                           private val httpClient = OkHttpClient.Builder()
                                  .addInterceptor (other interceptors)
                                  ........................................
                          
                                  //This Interceptor is the main logging Interceptor
                                  .addInterceptor { chain ->
                                      val request = chain.request()
                                      val jsonObj = JSONObject(Gson().toJson(request))
                          
                                      val requestBody = (jsonObj
                                      ?.getJSONObject("tags")
                                      ?.getJSONObject("class retrofit2.Invocation")
                                      ?.getJSONArray("arguments")?.get(0) ?: "").toString()
                                      val url = jsonObj?.getJSONObject("url")?.getString("url") ?: ""
                                      
                                      Timber.d("gsonrequest request url: $url")
                                      Timber.d("gsonrequest body :$requestBody")
                          
                                      chain.proceed(request)
                                  }
                                  
                                  ..............
                                  // Add other configurations
                                  .build()
                          

                          现在您的每个 Retrofit 调用的 URL 和请求正文都将记录在Logcat"gsonrequest"过滤

                          【讨论】:

                            【解决方案24】:

                            JSONObject 显示错误请使用

                            JsonObject paramObject = new JsonObject(); paramObject.addProperty("loginId", vMobile_Email);

                            【讨论】:

                            • 您好,当您使用代码示例时,请尝试使用正确的格式,这样会更清楚。
                            【解决方案25】:

                            添加 ScalarsConverterFactory.create() 方法并传递硬代码

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 2020-06-18
                              • 2019-12-11
                              • 2021-03-04
                              • 2019-06-06
                              • 1970-01-01
                              • 2017-06-17
                              相关资源
                              最近更新 更多