我是Android开发的新手。我正在尝试构建一个Android http客户端,该客户端向发送JSON的.NET Web API发出请求。
我正在使用:
- GSON 2.3对JSON进行序列化和反序列化,因为它支持流式传输,因为JSONObject不能很好地处理大型JSON(当它试图将整个JSON加载到内存中的String中时,它使用了太多内存)。我试着跟随https://sites.google.com/site/gson/streaming
- 安卓工作室内的安卓API 17
- HttpURLConnection作为推荐的客户端Httphttp://developer.android.com/reference/java/net/HttpURLConnection.html
我试图用JSON请求一个http PUT,服务器端的Web API获得了http请求,但它找不到任何JSON,所以我一定错过了我看不到的东西。。我甚至考虑过它在这里所说的:如何将JSON对象流式传输到关于使用connect()方法的HttpURLConnection POST请求,尽管HttpURLConnection文档没有提到它。
我的代码:
public void sendData(final String id, final int count, final MobileData myData)
throws WebApiException {
HttpURLConnection urlConnection = null;
final String urlSend = "http://myIISapi" + "/" + id + "?count=" + count;
try {
final URL url = new URL(urlSend);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0); //gets system default chunk size
urlConnection.setRequestMethod("PUT");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.connect(); //necessary?
final OutputStream outputStream = new BufferedOutputStream(urlConnection.getOutputStream());
final JsonWriter writer = new JsonWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.setIndent(" ");
Gson gson = new Gson();
//String parsed = gson.toJson(amsData, MobileAmsData.class);
gson.toJson(myData, MobileData.class, writer);
writer.flush();
writer.close();
final int statusCode = urlConnection.getResponseCode();
LOG.info("sendData server responded with status code = " + statusCode);
if (HttpURLConnection.HTTP_OK != statusCode) {
throw new WebApiException("Server did not accept data. Status code: " + statusCode);
}
}
catch (Exception e) {
throw new WebApiException("Unable to send PUT request", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
我是不是遗漏了一些必需的标题?我对发送JSON的流式传输方式有点困惑,所以问题可能存在。最后,是否有可能通过这样的流式传输数据,实际上有不止一个HTTP请求,服务器应该考虑数据正在流式传输?或者流式传输只在客户端以构建单个http请求的方式发生?
谢谢你们!
编辑:如果我明确地对JsonWriter对说
writer.beginObject();
之前
gson.toJson(myData,MobileData.class,writer);
那么它将抛出一个非法状态异常-嵌套问题。只是为了澄清,我试图使用混合GSON写作来利用混合流媒体&对象模型访问。因此,我试图获取MobileAmsData复杂对象,将其流序列化为JSON,并将其http PUT到远程服务器。
EDITED2:如果使用序列化,我尝试发送的JSON将如下所示
解析的字符串=gson.toJson(myData,MobileData.class);
{
"Things1":[
],
"Things2":[
],
"Things3":[
],
"Things4":[
],
"Things1Count":0,
"Things2Count":0,
"Things3Count":0,
"Things4Count":0,
"Count":2,
"BarcodeCount":1
}
在这里挣扎了很多之后,我发现了:
- 如果希望充分利用Android设备中的低内存使用率,则有必要使用分块传输编码。因此,HttpURLConnection应该设置一个分块流模式(0表示系统的默认值或任何其他字节数,例如1000,根据需要)
urlConnection.setChunkedStreamingMode(0);
-
当使用ChunkedStreamingMode时,Http请求将使用Transfer Encoding Http标头,但内容长度将为0这似乎是服务器端出现问题的原因,因为如果请求没有内容长度,我的ASP.NET Web Api方法无法反序列化JSON
-
如果我想充分利用GSON流模式,我需要添加一些智能功能来逐行写入JsonWriter(输出流),而不是一次写入整个对象。如果我打开流,然后一次解析Json并关闭流,我认为内存使用率将高于转换为Json并逐行写入的情况。(我在GSON文件中不太清楚这一点)
总之,上面的代码WORKS和它能够发送一个HTTP PUT请求,其中GSON将JSON流式传输到输出流中,并使用分块编码传输。。。但这不是一个高效的代码,如果内存使用是一个问题,应该重新处理以逐行序列化。