如何从JSONObject中删除nameValuePairs键?

13K*_*3KZ 23 rest android json retrofit

我正在研究一个Android项目,它需要一个JSONObject作为我的POST请求的主体.在放入JSON的键和值后,我得到以下行:

{
    "xxxx":"zzzzzzz",
    "yyyy":"uuuuuuu"
}
Run Code Online (Sandbox Code Playgroud)

但服务器得到以下内容:

{
    "name_value_pairs": {
                        "xxxx":"zzzzzzz",
                        "yyyy":"uuuuuuu"
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了一个JSONStringer但它并没有真正帮助,因为Content-Type请求是application/json.

UPDATE

我不是要构建一个JSONObject,因为它已经通过使用下面的代码行完成了(@osayilgan给出了相同的代码):

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Run Code Online (Sandbox Code Playgroud)

这不是问题.下面描述的接口用于与服务器通信.

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}
Run Code Online (Sandbox Code Playgroud)

服务器获得了第二个JSON作为Body的请求令人失望.我注意到密钥name_value_pairs会自动添加到对象中.

有谁知道我该如何解决这个问题?

Man*_*ani 26

问题:

默认情况下,Retrofit使用GSON将HTTP主体转换为JSON和从JSON转换.使用@Body注释指定的对象将传递给GSON进行序列化,这基本上将JAVA对象转换为JSON表示.此JSON表示将是HTTP请求正文.

JSONObject按名称将所有键值映射存储在成员变量中nameValuePairs.以下是JSONObject实现的摘录:

public class JSONObject {
    ...
    private final Map<String, Object> nameValuePairs;
    ...
}
Run Code Online (Sandbox Code Playgroud)

当您将JSONObject传递给@Body注释时,此JSONObject被封装,因此HTTP请求正文包含:{"nameValuePairs":"实际JSON对象"}.

解:

将实际的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);
Run Code Online (Sandbox Code Playgroud)

替代方案:

如果你仍然想发送原始JSON作为HTTP请求的身体,然后按照通过改造作者提到的解决方案在这里.

建议的解决方案之一是使用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);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答.这真的很有帮助.我发现了另一种避免使用密钥nameValuePairs的方法.我没有使用android的JSONObject,而是使用GSON的JsonObject,并使用方法addProperty(String property,_THEVALUE_)构造对象. (7认同)

Anu*_*tin 9

使用com.google.gson.JsonObject而不是org.json.JSONObject

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Run Code Online (Sandbox Code Playgroud)

改成

JsonObject jsonRequest = new JsonObject();
jsonRequest.addProperty("xxxx", "zzzzzzz");
jsonRequest.addProperty("yyyy", "uuuuuuu");
Run Code Online (Sandbox Code Playgroud)

然后在界面

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body JsonObject jsonObject, Callback<Response> callback);
}
Run Code Online (Sandbox Code Playgroud)

JSONObject 类将值保留在LinkedHashMap变量名称中nameValuePairs,当 Gson 尝试将 JSONObject 的实例转换为 JSON 时,GSON 保留结构(具有变量nameValuePairs)。导致这个问题。

  • 最后,正确而简短的答案!非常感谢。 (2认同)

gau*_*pta 8

您必须将 JSONObject 转换为 GSON 的 JsonObject

走这条路

 JsonParser jsonParser = new JsonParser();
  JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());
Run Code Online (Sandbox Code Playgroud)

然后传入身体

HashMap<String,Object> body=new HashMap();

 body.put("content",jsonObject);
Run Code Online (Sandbox Code Playgroud)