【问题标题】:Parse JSON from HttpURLConnection object从 HttpURLConnection 对象解析 JSON
【发布时间】:2012-05-17 01:32:40
【问题描述】:

我正在使用 Java 中的 HttpURLConnection 对象进行基本的 http 身份验证。

        URL urlUse = new URL(url);
        HttpURLConnection conn = null;
        conn = (HttpURLConnection) urlUse.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-length", "0");
        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setConnectTimeout(timeout);
        conn.setReadTimeout(timeout);
        conn.connect();

        if(conn.getResponseCode()==201 || conn.getResponseCode()==200)
        {
            success = true;
        }

我期待一个 JSON 对象,或有效 JSON 对象格式的字符串数据,或带有有效 JSON 的简单纯文本的 HTML。 HttpURLConnection 返回响应后如何访问它?

【问题讨论】:

  • 请注意,所有 2xx HTTP 状态码都表示成功。

标签: java html json parsing httpurlconnection


【解决方案1】:

您可以使用以下方法获取原始数据。顺便说一句,此模式适用于 Java 6。如果您使用的是 Java 7 或更高版本,请考虑try-with-resources pattern

public String getJSON(String url, int timeout) {
    HttpURLConnection c = null;
    try {
        URL u = new URL(url);
        c = (HttpURLConnection) u.openConnection();
        c.setRequestMethod("GET");
        c.setRequestProperty("Content-length", "0");
        c.setUseCaches(false);
        c.setAllowUserInteraction(false);
        c.setConnectTimeout(timeout);
        c.setReadTimeout(timeout);
        c.connect();
        int status = c.getResponseCode();

        switch (status) {
            case 200:
            case 201:
                BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line+"\n");
                }
                br.close();
                return sb.toString();
        }

    } catch (MalformedURLException ex) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
    } finally {
       if (c != null) {
          try {
              c.disconnect();
          } catch (Exception ex) {
             Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
          }
       }
    }
    return null;
}

然后您可以使用返回的字符串和Google Gson 将 JSON 映射到指定类的对象,如下所示:

String data = getJSON("http://localhost/authmanager.php");
AuthMsg msg = new Gson().fromJson(data, AuthMsg.class);
System.out.println(msg);

有一个 AuthMsg 类的示例:

public class AuthMsg {
    private int code;
    private String message;

    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

http://localhost/authmanager.php 返回的 JSON 必须如下所示:

{"code":1,"message":"Logged in"}

问候

【讨论】:

  • 请问您在哪里关闭连接c
  • 最初我是用 java 7 的方式用 try-with-resources 写的,但是有人决定保留 java 6,所以最后忽略了连接关闭。但是,是的,必须关闭连接。稍后我会编辑这个,谢谢。
  • @kbec 我仍然看不到您关闭连接的位置。您能否将其添加到您的答案中?
  • @kbec HttpURLConnection 没有关闭你的意思是disconnect()
  • 也许,捕捉 MalformedURLException 是没用的,因为已经有 IOException 了?
【解决方案2】:

此函数将用于从 url 以 HttpResponse 对象的形式获取数据。

public HttpResponse getRespose(String url, String your_auth_code){
HttpClient client = new DefaultHttpClient();
HttpPost postForGetMethod = new HttpPost(url);
postForGetMethod.addHeader("Content-type", "Application/JSON");
postForGetMethod.addHeader("Authorization", your_auth_code);
return client.execute(postForGetMethod);
}

这里调用了上面的函数,我们使用 Apache 库 Class 接收到一个字符串形式的 json。在下面的语句中,我们尝试从我们收到的 json 中制作简单的 pojo。

String jsonString     =     
EntityUtils.toString(getResponse("http://echo.jsontest.com/title/ipsum/content/    blah","Your_auth_if_you_need_one").getEntity(), "UTF-8");
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(JsonJavaModel .class, new    CustomJsonDeserialiser());
final Gson gson = gsonBuilder.create();
JsonElement json = new JsonParser().parse(jsonString);
JsonJavaModel pojoModel = gson.fromJson(
                    jsonElementForJavaObject, JsonJavaModel.class);

这是一个用于传入 json 的简单 java 模型类。 公共类 JsonJavaModel{ 字符串内容; 字符串标题; } 这是一个自定义反序列化器:

public class CustomJsonDeserialiserimplements JsonDeserializer<JsonJavaModel>         {

@Override
public JsonJavaModel deserialize(JsonElement json, Type type,
                                 JsonDeserializationContext arg2) throws    JsonParseException {
    final JsonJavaModel jsonJavaModel= new JsonJavaModel();
    JsonObject object = json.getAsJsonObject();

    try {
     jsonJavaModel.content = object.get("Content").getAsString()
     jsonJavaModel.title = object.get("Title").getAsString()

    } catch (Exception e) {

        e.printStackTrace();
    }
    return jsonJavaModel;
}

包含 Gson 库和 org.apache.http.util.EntityUtils;

【讨论】:

    【解决方案3】:

    此外,如果您希望在 http 错误(400-5** 代码)的情况下解析您的对象, 您可以使用以下代码:(只需将 'getInputStream' 替换为 'getErrorStream':

        BufferedReader rd = new BufferedReader(
                new InputStreamReader(conn.getErrorStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();
        return sb.toString();
    

    【讨论】:

      【解决方案4】:

      JSON 字符串将只是您从调用的 URL 返回的响应的主体。所以添加这段代码

      ...
      BufferedReader in = new BufferedReader(new InputStreamReader(
                                  conn.getInputStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null) 
          System.out.println(inputLine);
      in.close();
      

      这将允许您看到 JSON 返回到控制台。您唯一缺少的部分是使用 JSON 库来读取该数据并为您提供 Java 表示。

      Here's an example using JSON-LIB

      【讨论】:

      • 如果读取输入时出现异常,输入缓冲区不会关闭。
      【解决方案5】:

      定义如下函数(不是我的,不知道很久以前在哪里找到的):

      private static String convertStreamToString(InputStream is) {
      
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      StringBuilder sb = new StringBuilder();
      
      String line = null;
      try {
          while ((line = reader.readLine()) != null) {
              sb.append(line + "\n");
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          try {
              is.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      return sb.toString();
      

      }

      然后:

      String jsonReply;
      if(conn.getResponseCode()==201 || conn.getResponseCode()==200)
          {
              success = true;
              InputStream response = conn.getInputStream();
              jsonReply = convertStreamToString(response);
      
              // Do JSON handling here....
          }
      

      【讨论】:

      • convertStreamToString 不会通知调用代码如果连接在传输过程中丢失,则字符串不完整。一般来说,最好让异常冒泡。
      猜你喜欢
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      相关资源
      最近更新 更多