- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 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/
我正在尝试在引号内使用引号。它在文本框内工作,但在我需要字符串的地方不工作。例如,第一行代码有效,但我需要将字符串作为变量。 pictureBox1.Image = MediaLib.Get["che
我需要找到一种方法来检查字符串中的双引号,以便将输出写入 XML 文档,然后在 Word 中打开。我想出了如何查找像 (') 这样的单引号,但是双引号在我的 XML 文档中引发了错误。 pr
我正在尝试在引号内使用引号。它在文本框内工作,但在我需要字符串的地方不工作。例如,第一行代码有效,但我需要将字符串作为变量。 pictureBox1.Image = MediaLib.Get["che
我定义了一个由动态变量组成的变量 var tempVar = ""; varName输出Black/Blue Mirror + some special character with single a
我在 Jenkins 管道中运行了这个 shell 脚本 def planResults = sh(returnStdout: true, script: "cd $it; PLAN=\$(terra
双引号 ("") 怎么可能有一个方法,即使您实际上没有在 String 中声明它。例如: System.out.println("".length()); "" 是否已经是一个对象,但没有在 Stri
我刚刚开始阅读“Head First Java”这本书。由于下面代码中没有空格的双引号 (""),有一个练习让我感到困惑。我想我明白了,但看起来这本书并没有解释它,我想确保我是正确的。 下面代码中双引
我有一个名为 myfield 的字段,其中包含以下字符串: {'Content-Language': 'en', 'X-Frame-Options': 'SAMEORIGIN', 'X-Generat
这是一个 nodejs 正则表达式,它将引号替换为 json 解析器接受的新模式。 var someStr = "this string has one single quote ': this st
当查询列表并将值放入变量并尝试在另一个脚本中使用该变量时,它确实获得了所需的格式。 脚本 1: cilist=$(opr-ci-list.sh -view_name TN_UD_REFRESH_MRE
我正在尝试在 powershell 中调用 curl 命令并传递一些 JSON 信息。 这是我的命令: curl -X POST -u username:password -H "Content-Ty
我使用 terraform 创建了一个 YML 管道。 它使用脚本任务并在输出中返回 Web 应用程序名称 steps: - script: | [......] terraform
我的项目由Docker包装,并在2种环境中运行:代理后面的或没有代理的。 在这种情况下,我使用php:apache镜像并通过pecl安装ext,因此必须手动设置代理 FROM php:apache R
我是 Clang-Format 的新手。 我使用 ./bin/clang-format -style=google -dump-config > .clang-format 作为我的基础 .clang
我试图在从数据库读取数据后生成 CSV 文件。现在单个数据可以包含逗号、单引号和双引号。 请告诉我如何在正则表达式的帮助下处理这种情况。 最佳答案 您可以为 CSV 文件使用不同的分隔符吗?也许是一个
我全新安装了 janus vim 插件和 macvim。 由于某种原因,当我在 macvim 中打开 .json 文件时,.json 文件中的键或值周围没有双引号。当我向下滚动文件的行时,双引号会显示
我的属性结构如下: my { property { item { "1" { value="some value"
这个问题已经有答案了: How to escape single quotes in MySQL (19 个回答) 已关闭 5 年前。 考虑这个表 CREATE TABLE name ( nom VA
我面临 SyntaxError: unterminated string literal* 尝试在文本区域中设置值时出错。 这里,文本值是动态的,从后端接收,可以包含任何字符。 经过我的第一次调查,我
我正在尝试设置包含单引号的属性值: var attr_value = "It's not working"; var html = "Text"; $('body').html(html); 但是,我
我是一名优秀的程序员,十分优秀!