我正在开发一个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");
这不是问题。下面描述的接口用于与服务器通信。
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}
服务器获得了第二个JSON作为Body的请求,这令人失望。我注意到密钥name_value_pairs
会自动添加到对象中。
有谁知道如何解决这个问题?
答案 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 jsonObject
到String 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.