gpt4 book ai didi

Android 在较新版本中使用 String Query param 双引号改造 POST 方法

转载 作者:行者123 更新时间:2023-11-29 01:03:05 24 4
gpt4 key购买 nike

我有一个 API 的改造方法:

@POST("/searchCity/byname")
Call<Cities> searchCityByName(@Query("name") String name);

从代码中以这种方式调用它:

final String cityName ="City"
restClient.getApiService().searchCityByName(cityName);

每当我使用retrofit 2.1.0 发送请求时,url 是以下一个(正确):

searchCity/byname?name=City

但是,当我使用retrofit 2.2.0 及更高版本 发送相同的请求时,url 更改为(不正确):

searchCity/byname?name=%22City%22

至此,由于编码的双引号(%22 解码为 "),服务器在处理请求时失败。

我已经按照程序流程进行操作,但我什么也没发现...可能发生了什么?

我需要在拥有第一个 URL(没有引号的那个)的同时使用 retrofit 2.3.0。有什么办法可以实现吗?

编辑 - 2018 年 4 月 3 日:

这里是用到的类:

RetrofitClient.java

@EBean(scope = EBean.Scope.Singleton)
public class RetrofitClient {
private static volatile Retrofit retrofit;
private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://exampleserver.com/");
private PrivateApi apiService;

public static <S> S createService(Class<S> serviceClass) {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
retrofit = builder.client(new WebClient().getClient())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit.create(serviceClass);
}

@AfterInject
public void privateRestClientAfterInject() {
final PrivateApi apiService = createService(PrivateApi.class);
final PrivateApiServiceInvocationHandler publicApiServiceInvocationHandler = new
PrivateApiServiceInvocationHandler(apiService);
this.apiService = (PrivateApi) Proxy.newProxyInstance(PrivateApi.class.getClassLoader(),
new Class[]{PrivateApi.class}, publicApiServiceInvocationHandler);
}

public PrivateApi getApiService() {
if (apiService == null) {
privateRestClientAfterInject();
}
return apiService;
}
}

WebClient.java

public class WebClient {

public OkHttpClient getClient() {
final HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor
.Level.BODY);

final OkHttpClient.Builder builder = new OkHttpClient.Builder().readTimeout
(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.addInterceptor(logging)
.followRedirects(false)
.followSslRedirects(false);



builder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final HttpUrl newurl = originalRequest.url().newBuilder().build();
final Request newRequest = originalRequest.newBuilder()
.url(newurl)
.headers(originalRequest.headers())
.header("Connection", "close")
.header("User-Agent",
getUserAgentAndKeyboard())
.method(originalRequest.method(), originalRequest.body())
.build();
return chain.proceed(newRequest);
}
});
return builder.build();
}

/**
* Returns the standard user-agent with the default input method brand name
*
* @return The concatenated "user-agent; keyboard" string
*/
private static String getUserAgentAndKeyboard() {
// WEWE-857
ContentResolver contentResolver = BaseApplication.getInstance().getContentResolver();
if (contentResolver != null) {
String keyboard = Settings.Secure.getString(contentResolver, Settings.Secure
.DEFAULT_INPUT_METHOD);
return String.format(Locale.getDefault(), "%s;%s", System.getProperty("http.agent"),
keyboard);
}
return System.getProperty("http.agent");
}

}

RetrofitInvocationHandler.java

public class RetofitInvocationHandler implements InvocationHandler {

private final Object target;

public RetofitInvocationHandler(Object target) {
super();
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}

PrivateApi.java

public interface PrivateApi {
@Headers({
"Content-Type:application/json"
})
@POST("/searchCity/byname")
Call<Cities> searchCityByName(@Query("name") String name);
}

最佳答案

最后我得到了解决方案:

只需添加一个自定义转换器来重写查询参数:

public static <S> S createService(Class<S> serviceClass) {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
retrofit = builder.client(new WebClient().getClient())
.addConverterFactory(GsonConverterFactory.create(gson))
// custom interceptor
.addConverterFactory(new StringConverterFactory(GsonConverterFactory.create(gson)))
// custom interceptor
.build();
return retrofit.create(serviceClass);
}

StringCoverterFactory.java

public class DateStringConverterFactory extends Converter.Factory {

private final Converter.Factory delegateFactory;

DateStringConverterFactory(Converter.Factory delegateFactory) {
super();
this.delegateFactory = delegateFactory;
}

@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit
retrofit) {
for (final Annotation annotation : annotations) {
if (annotation instanceof Query) {

final Converter<?, RequestBody> delegate = delegateFactory
.requestBodyConverter(type, annotations, new Annotation[0], retrofit);
return new DelegateToStringConverter<>(delegate);
}
}
return null;
}


static class DelegateToStringConverter<T> implements Converter<T, String> {
private final Converter<T, RequestBody> delegate;

DelegateToStringConverter(Converter<T, RequestBody> delegate) {
this.delegate = delegate;
}

@Override
public String convert(T value) throws IOException {
final okio.Buffer buffer = new okio.Buffer();
delegate.convert(value).writeTo(buffer);
if(value instanceof String){
return value.toString();
}
else {
return buffer.readUtf8();
}
}
}
}

感谢所有尝试做出贡献的人!!

关于Android 在较新版本中使用 String Query param 双引号改造 POST 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49613331/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com