【问题标题】:HttpURLConnect - Http PUT with JSON using GSON streaming not sending contentHttpURLConnect - 使用 GSON 流的带有 JSON 的 Http PUT 不发送内容
【发布时间】:2014-11-24 08:48:10
【问题描述】:

我是 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();
        }
    }
}

我是否缺少一些强制性标题?我对发送 JSON 的流式传输方式有点困惑,所以问题可能就在那里。最后,是否有可能通过这样的流式传输数据实际上有多个 HTTP 请求并且服务器应该认为数据正在流式传输?或者流仅在客户端以构建单个 http 请求的方式发生?

谢谢你们!

已编辑:如果我明确对 JsonWriter 说

writer.beginObject();

之前

gson.toJson(myData, MobileData.class, writer);

然后它会抛出一个IllegalStateException - 嵌套问题。澄清一下,我正在尝试使用混合 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 json stream gson httpurlconnection


    【解决方案1】:

    在这里挣扎了很多之后,这就是我发现的:

    • 如果希望充分利用 Android 设备的低内存使用率,则必须使用块传输编码。所以 HttpURLConnection 应该设置一个分块流模式(系统默认为 0 或任何其他字节数,例如 1000,根据需要)

    urlConnection.setChunkedStreamingMode(0);

    • 当使用 ChunkedStreamingMode 时,Http 请求将使用 Transfer-Encoding HTTP 标头,但 Content-Length 将为 0。这似乎是我的 ASP 在服务器端引起问题的原因。如果请求没有内容长度,NET Web Api 方法无法反序列化 JSON

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-26
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      相关资源
      最近更新 更多