如何从JSONObject中删除nameValuePairs键?

时间:2014-09-24 16:37:17

标签: android json rest retrofit

我正在开发一个Android项目,该项目需要一个JSONObject作为我的POST请求的正文。 在放入JSON的键和值后,我得到以下行:

{
    "xxxx":"zzzzzzz",
    "yyyy":"uuuuuuu"
}

但服务器得到以下内容:

{
    "name_value_pairs": {
                        "xxxx":"zzzzzzz",
                        "yyyy":"uuuuuuu"
    }
}

我已经尝试过JSONStringer,但它并不是真正有用,因为请求的Content-Typeapplication/json

更新

我没有尝试构建JSONObject,因为它已经通过使用以下代码行完成了(@osayilgan给出了相同的代码):

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");

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

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

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

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

7 个答案:

答案 0 :(得分:25)

问题

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

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

public class JSONObject {
    ...
    private final Map<String, Object> nameValuePairs;
    ...
}

当您将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);

替代解决方案:

如果您仍想将原始JSON作为HTTP请求正文发送,请按照Retrofit作者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);

答案 1 :(得分:2)

您必须将JSONObject转换为JsonObject

按照这种方式

 JsonParser jsonParser = new JsonParser();
  JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());

然后通过身体

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

 body.put("content",jsonObject);

答案 2 :(得分:1)

感谢13KZ,指出了我正确的方向,并且在这里充实它是我现在必须解决的问题。

解释

private JsonObject gsonResultTwoWeek;
private JsonObject gsonResultDay;
private JsonObject gsonResult;

初​​始化

gsonResult = new JsonObject();
gsonResultDay = new JsonObject();
gsonResultTwoWeek = new JsonObject();

使用

gsonResultDay.addProperty(epoch, value);

其中data是一个字符串,在我的情况下value是一个int,并且在for循环中添加多个值

然后将它们全部拉到一起

gsonResult.addProperty("accounts", 2);
gsonResult.add("todaydata", gsonResultDay);
gsonResult.add("2weekdata", gsonResultTwoWeek);

最后我的界面

public interface ApiInterface {

    @POST("/groupdata")
    void postGroupData(@Body JsonObject body,Callback<StatusResponse> cb);

}

我的服务器是什么打击

{"accounts":2,"todaydata":{"1423814400":89,"1423816200":150,"1423818000":441},"2weekdata":{"1423699200":4869,"1423785600":1011}}

答案 3 :(得分:0)

您似乎正在尝试传输实际的JSONObject而不是对象的JSON文本字符串表示。查看JSONObject类的规范表明您应该使用.toString()方法来获取JSONObject保留的数据结构的JSON文本表示。因此,您应该能够改变:

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

为:

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body String jsonObject.toString(), Callback<Response> callback);
}

唯一的变化是JSONObject jsonObjectString jsonObject.toString()

或者,您可以通过仅使用JSON的字符串来强制它,并将'"name_value_pairs": {'替换为'',将'}'替换为{{1} }}。 JSON只是一串文本。除了它不优雅之外,没有理由不能操纵文本。这两个替换将导致有效的JSON文本对象。空白缩进对人类来说看起来不正确,但是解析JSON字符串的机器并不关心空格是否正确。

答案 4 :(得分:0)

我的解决方案基于13KZ&#39>

public class MyRequest {

  @SerializedName(Constants.ID)
  private String myID;
  @SerializedName(Constants.PARAM_ANSWERS)
  private JsonObject answers;

     public MyRequest(String id, Hasmap<String, String> answers) {
         this.myID = id;
         this.answers = new JsonObject();
         for (String s: answers.keySet()) {
             this.answers.addProperty(s, answers.get(s));
         }
     }
}

答案 5 :(得分:0)

使用 com.google.gson.JsonObject 代替 org.json.JSONObject

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");

更改为

JsonObject jsonRequest = new JsonObject();
jsonRequest.addProperty("xxxx", "zzzzzzz");
jsonRequest.addProperty("yyyy", "uuuuuuu");

然后进入界面

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

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

答案 6 :(得分:0)

    JSONObject jsonRequest = new JSONObject();
                    try {
                        jsonRequest.put("abc", "test");
                        jsonRequest.put("cba", "tye");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    Log.d("jsonobject", "onClick: "+jsonRequest);

    (result: {"abc":"test","cba":"tye"})

    JsonParser jsonParser = new JsonParser();
    JsonObject jsonObject = (JsonObject)jsonParser.parse(jsonRequest.toString());

                Log.d("jsonobjectparse", "onClick: "+jsonObject);

(result: {"abc":"test","cba":"tye"})

Once you are put the values into the jsonObject pass to the jsonParser it will solve the issue

thats all. enjoy your coding.