我是 Android 开发新手。我正在尝试构建一个 Android http 客户端,该客户端向发送 JSON 的 .NET Web API 发出请求。
我正在使用:
- GSON 2.3 序列化-反序列化 JSON,因为它支持流式传输,因为 JSONObject 不能很好地处理大型 JSON(它使用太多内存,因为它尝试将整个 JSON 加载到内存中的字符串中)。我试图关注https://sites.google.com/site/gson/streaming
- Android Studio 中的 Android API 17
- HttpURLConnection 作为 http://developer.android.com/reference/java/net/HttpURLConnection.html 推荐的客户端 Http
我正在尝试使用 JSON 请求 http PUT,服务器端的 Web API 获取 http 请求,但它无法找到任何 JSON,所以我一定错过了一些我看不到的东西。我什至考虑过什么它在这里说:How to stream a JSON object to a HttpURLConnection POST request关于使用 connect() 方法,尽管 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();
}
}
}
我是否缺少一些强制 header ?我对发送 JSON 的流式传输方式有点困惑,所以问题可能就在那里。最后,是否有可能通过这样的流式传输数据,实际上存在多个 HTTP 请求,并且服务器应该考虑数据正在流式传输?或者流仅在客户端以构建单个 http 请求的方式发生?
谢谢大家!
已编辑:如果我明确对 JsonWriter 说
writer.beginObject();
之前
gson.toJson(myData, MobileData.class, writer);
然后它将抛出一个IllegalStateException - 嵌套问题。只是为了澄清,我正在尝试使用混合 GSON 编写来利用混合流和对象模型访问。因此,我尝试获取 MobileAmsData 复杂对象,将其流序列化为 JSON,然后通过 http 将其发送到远程服务器。
EDITED2: 如果使用
序列化,我尝试发送的 JSON 将如下所示String parsed = 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 header ,但 Content-Length 将为 0。 这似乎是在我的 ASP 中导致服务器端出现问题的原因。如果请求没有内容长度,. NET Web Api 方法无法反序列化 JSON
如果我想充分利用 GSON 流模式,我需要添加一些智能功能来逐行写入 JsonWriter(输出流),而不是一次写入整个对象。如果我打开流,然后一次性解析 Json 并关闭流,我认为内存使用量会比转换为 Json 并逐行写入更高。 (GSON 文档中我对此不太清楚)
作为总结,上面的代码可以工作,并且能够使用 GSON 流式 JSON 发送 HTTP PUT 请求到输出流并使用分块编码传输...但它不是有效的代码,应该重新设计以序列化行如果内存使用有问题,则按行。
关于android - HttpURLConnect - 使用 GSON 流的带有 JSON 的 Http PUT 不发送内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26108722/