android - HttpURLConnect - 使用 GSON 流的带有 JSON 的 Http PUT 不发送内容

标签 android json stream gson httpurlconnection

我是 Android 开发新手。我正在尝试构建一个 Android http 客户端,该客户端向发送 JSON 的 .NET Web API 发出请求。

我正在使用:

我正在尝试使用 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

  • 如果我想充分利用 GS​​ON 流模式,我需要添加一些智能功能来逐行写入 JsonWriter(输出流),而不是一次写入整个对象。如果我打开流,然后一次性解析 Json 并关闭流,我认为内存使用量会比转换为 Json 并逐行写入更高。 (GSON 文档中我对此不太清楚)

作为总结,上面的代码可以工作,并且能够使用 GSON 流式 JSON 发送 HTTP PUT 请求到输出流并使用分块编码传输...但它不是有效的代码,应该重新设计以序列化行如果内存使用有问题,则按行。

关于android - HttpURLConnect - 使用 GSON 流的带有 JSON 的 Http PUT 不发送内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26108722/

相关文章:

android - hidraw 设置报告/发送报告不适用于 Android 6.x

php - 使用 HTTP Session VS 序列化 JSON 数组来存储 SQL 结果

php - 在 laravel 护照客户端应用程序中使用访问 token 获取用户数据

ruby-on-rails - 有没有办法在 Rails Jbuilder 模板中隐藏属性?

流式传输中的 Android MediaRecorder

java - 是否可以禁止关闭 Android 应用程序?

java - Java 中的良好方法实践

c++ - 如何流式传输 std::variant<...,...>

android - 如何将渲染器注入(inject)到 SimpleExoPlayer

spring - Spring-xd Stream正在将空文件写入我的HDFS