我正在开发一个 Android 项目,该项目需要一个 JSONObject 作为我的 POST 请求的正文。 放置 JSON 的键和值后,我得到以下行:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
但是服务器得到了以下信息:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
我已经尝试过 JSONStringer,但它并没有真正的帮助,因为请求的 Content-Type
是 application/json
。
更新
我没有尝试构造 JSONObject,因为它已经通过使用以下代码行完成(@osayilgan 给出的相同):
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
这不是问题所在。下面描述的接口(interface)用于与服务器通信。
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}
服务器收到了第二个 JSON 作为正文的请求,这令人失望。我注意到键 name_value_pairs
会自动添加到对象中。
有人知道我该如何解决这个问题吗?
最佳答案
问题:
Retrofit 默认使用 GSON 将 HTTP 正文与 JSON 进行转换。 @Body 注解指定的对象将被传递给 GSON 进行序列化,这基本上将 JAVA 对象转换为 JSON 表示。此 JSON 表示将是 HTTP 请求正文。
JSONObject 将所有键值映射存储在一个名为 nameValuePairs
的成员变量中。
下面是 JSONObject 实现的摘录:
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
当您将 JSONObject 传递给 @Body 注释时,此 JSONObject 会被序列化,因此 HTTP 请求正文包含:{"nameValuePairs": "actual JSON Object"}。
解决方案:
将实际的 JAVA 对象传递给 @Body 注释,而不是对应的 JSONObject。 GSON 将负责将其转换为 JSON 表示形式。
例如
class HTTPRequestBody {
String key1 = "value1";
String key2 = "value2";
...
}
// GSON will serialize it as {"key1": "value1", "key2": "value2"},
// which will be become HTTP request body.
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void postJson(@Body HTTPRequestBody body, Callback<Response> callback);
}
// Usage
MyService myService = restAdapter.create(MyService.class);
myService.postJson(new HTTPRequestBody(), callback);
替代解决方案:
如果您仍想将原始 JSON 作为 HTTP 请求正文发送,请按照改造作者 here 中提到的解决方案进行操作。 .
建议的解决方案之一是使用 TypedInput :
public interface MyService {
@POST("/test")
void postRawJson(@Body TypedInput body, Callback<Response> callback);
}
String json = jsonRequest.toString();
TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
myService.postRawJson(in, callback);
https://stackoverflow.com/questions/26022133/