从HttpURLConnection对象解析JSON

67

我正在使用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;
        }

我希望从HttpURLConnection返回的响应中获取一个JSON对象、格式正确的JSON字符串数据或包含有效JSON纯文本的HTML。如何访问它?


3
注意,所有以2xx开头的HTTP状态码均表示成功。 - Fred
5个回答

121

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

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"}

敬礼


1
我可以问一下,你在哪里关闭了连接“c”吗? - Gödel77
1
@kbec HttpURLConnection没有close方法,你是不是想用“disconnect()”? - Michael
fromJson() 是一个非静态方法,请修正答案。 - filippo
getJson()方法不应该返回sb吗? - Apurva
getJson() 可以返回 ByteBuffer,如果您需要的话。 - kbec
显示剩余6条评论

11

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

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 不会通知调用代码字符串不完整。通常最好让异常冒泡。 - Edward Brey

4
此外,如果您希望在出现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();

2
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表示。

这里有一个使用JSON-LIB的例子


如果读取输入时出现异常,则输入缓冲区不会关闭。 - Edward Brey

0

这个函数将被用来获取以HttpResponse对象形式返回的URL数据。

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库类接收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模型类。 public class JsonJavaModel{ String content; String title; } 这是一个自定义反序列化器:

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;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接