在 Retrofit 中的请求正文之前添加字符串

Adding string before request body in Retforit

我想在 Retrofit 请求中的请求正文之前添加字符串。 我的意思是:

data={"action":"users.login","data":{"email":"test@gmail.com", "password":"password"}}

但是 Retofit 只允许这样的请求:

{"action":"users.login","data":{"email":"test@gmail.com", "password":"password"}}

这是我在接口中的方法代码:

@POST("/api")
Observable<RequestResult> loginAction(@Body Request<User> userRequest);

这是来自登录的代码 activity:

User user = new User();
user.setEmail("email");
user.setPassword("password");

    subscription.add(
            service.loginAction(
                    new Request<>("users.login", user))
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<RequestResult>() {
                @Override
                public void onCompleted() {
                }
                @Override
                public void onError(Throwable e) {
                }
                @Override
                public void onNext(RequestResult requestResult) {
                }
            })
    );

首先,如果您想在每个请求之前添加字符串,可以使用 OkHttp interceptor.

指定它们

就这样,

    client.interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            String time = DateUtil.getDefaultDateTime(new Date());


            RequestBody body = request.body();

            String bodyData = "data=";

            if (body != null) {
                Buffer bufferedSink = new Buffer();
                request.body().writeTo(bufferedSink);
                bodyData += bufferedSink.readUtf8();
            }

            String tokenData = AppContext.get(ContextConstant.TOKEN, "");

            String keyData = request.url() + bodyData + time + tokenData;

            String key = Encryption.genKey(keyData);

            String userId = AppContext.get(ContextConstant.CURRENT_USER_ID, "");

            String authorization = Encryption.getHeaderValue(userId, AppContext.getInstance().getUUID());

            Request.Builder requestBuilder = request.newBuilder();

            requestBuilder.header("X-key", key);
            requestBuilder.header("Authorization", authorization.replace("\n", ""));
            requestBuilder.header("X-API-Version", AppConstant.API_VERSION);
            requestBuilder.header("X-Data-version", AppConstant.DATA_VERSION);
            requestBuilder.header("X-Request-Time", time);

            Request okRequest = requestBuilder.build();

            Response response = chain.proceed(okRequest);

            return response;
        }

    });

但是,我只对指定的Header使用这种方式,而不是对指定的RequestBody。

其次,如果你使用 Gson,(不幸的是,你没有)

        Gson gson = new GsonBuilder()
            .setDateFormat(DateUtil.FORMAT)
            .registerTypeAdapter(User.class, new UserDeserializer())
            .registerTypeAdapter(User.class, new UserSerializer())
            .create();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(AppConstant.HOST)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(client)
            .build();

在 UserSerializer 中,

public class UserSerializer implements JsonSerializer<User> {
@Override
public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive("data=" + src.toString());
}

}

我认为它可以由 {} 循环......

{data={"action":"users.login","data":{"email":"test@gmail.com", "password":"password"}}}

最后,我建议您使用包装器 class UserData 将 "data=" 封装在请求字符串中。

我使用 Retrofit 2.0 beta 2。

祝你好运!