How to POST raw whole JSON in the body of a Retrofit request?

前端 未结 23 2397
面向向阳花
面向向阳花 2020-11-22 00:57

This question may have been asked before but no it was not definitively answered. How exactly does one post raw whole JSON inside the body of a Retrofit request?

See

23条回答
  •  攒了一身酷
    2020-11-22 01:40

    Yes I know it's late, but somebody would probably benefit from this.

    Using Retrofit2:

    I came across this problem last night migrating from Volley to Retrofit2 (and as OP states, this was built right into Volley with JsonObjectRequest), and although Jake's answer is the correct one for Retrofit1.9, Retrofit2 doesn't have TypedString.

    My case required sending a Map that could contain some null values, converted to a JSONObject (that won't fly with @FieldMap, neither does special chars, some get converted), so following @bnorms hint, and as stated by Square:

    An object can be specified for use as an HTTP request body with the @Body annotation.

    The object will also be converted using a converter specified on the Retrofit instance. If no converter is added, only RequestBody can be used.

    So this is an option using RequestBody and ResponseBody:

    In your interface use @Body with RequestBody

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

    In your calling point create a RequestBody, stating it's MediaType, and using JSONObject to convert your Map to the proper format:

    Map 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 response = serviceCaller.login("loginpostfix", body);
          
    response.enqueue(new Callback()
        {
            @Override
            public void onResponse(Call call, retrofit2.Response rawResponse)
            {
                try
                {
                 //get your response....
                  Log.d(TAG, "RetroFit2.0 :RetroGetLogin: " + rawResponse.body().string());
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onFailure(Call call, Throwable throwable)
            {
            // other stuff...
            }
        });
    

    Hope this Helps anyone!


    An elegant Kotlin version of the above, to allow abstracting the parameters from the JSON convertion in the rest of your application code:

    interface ServiceApi {
    
        fun login(username: String, password: String) =
                jsonLogin(createJsonRequestBody(
                    "username" to username, "password" to password))
    
        @POST("/api/login")
        fun jsonLogin(@Body params: RequestBody): Deferred
    
        private fun createJsonRequestBody(vararg params: Pair) =
                RequestBody.create(
                    okhttp3.MediaType.parse("application/json; charset=utf-8"), 
                    JSONObject(mapOf(*params)).toString())
    
    }
    

提交回复
热议问题