如何在OkHttp3 Interceptor中为请求体添加公共JSON字段?
在OkHttp3拦截器中统一添加通用JSON请求字段
要解决这个问题,核心思路是重新构建请求体——因为OkHttp的RequestBody是不可变的,我们需要读取原请求体的JSON内容,注入通用字段后生成新的请求体,再替换原请求继续执行。下面是具体实现步骤和代码:
实现步骤
- 先判断原请求是否为JSON类型(避免处理表单、二进制等非JSON请求)
- 读取原请求体的JSON内容,转换为可修改的
JsonObject - 注入通用字段(比如
traceId) - 将修改后的JSON转换为新的
RequestBody - 构建新的请求,替换原请求后继续执行拦截链
完整代码实现
因为你的Retrofit已经使用了GsonConverterFactory,项目里应该已经引入了Gson依赖,直接修改MyInterceptor即可:
import com.google.gson.JsonObject import com.google.gson.JsonParser import okhttp3.* import okio.Buffer import java.nio.charset.Charset class MyInterceptor : Interceptor { private val UTF8 = Charset.forName("UTF-8") private val fixedTraceId = "abc123" // 你的通用字段值,若需动态生成可调整逻辑 override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() val originalBody = originalRequest.body() // 1. 无请求体或非JSON请求直接放行 if (originalBody == null || !isJsonRequest(originalRequest)) { return chain.proceed(originalRequest) } // 2. 读取原请求体的JSON内容 val buffer = Buffer() originalBody.writeTo(buffer) val originalJsonStr = buffer.readString(UTF8) val jsonObject = JsonParser.parseString(originalJsonStr).asJsonObject // 3. 注入通用字段 jsonObject.addProperty("traceId", fixedTraceId) // 4. 生成新的请求体 val newBody = RequestBody.create( originalBody.contentType(), jsonObject.toString() ) // 5. 构建新请求并执行 val newRequest = originalRequest.newBuilder() .method(originalRequest.method(), newBody) .build() return chain.proceed(newRequest) } // 判断请求是否为JSON类型 private fun isJsonRequest(request: Request): Boolean { val contentType = request.body()?.contentType() return contentType != null && contentType.subtype.contains("json", ignoreCase = true) } }
注意事项
- 非JSON请求兼容:代码会自动跳过表单、二进制等非JSON请求,若需要处理这类请求,可以单独扩展逻辑。
- 请求体重复读取问题:使用
Buffer读取原请求体,不会影响后续请求执行,因为Buffer支持重复读取。 - 动态字段支持:如果
traceId需要每个请求生成不同的值(比如UUID),只需修改fixedTraceId的生成逻辑,注意保证线程安全即可。 - Content-Length自动处理:OkHttp会自动计算新请求体的
Content-Length,无需手动设置,除非你手动指定了原请求的该头字段,此时需要同步更新。
这样修改后,所有JSON类型的POST/PUT请求都会自动带上traceId字段啦!
内容的提问来源于stack exchange,提问作者Stack Diego
相关产品推荐
相关产品推荐

