簡體   English   中英

從 Java 中的 URL 讀取 JSON 的最簡單方法

[英]Simplest way to read JSON from a URL in Java

這可能是一個愚蠢的問題,但是從Java中的URL讀取和解析JSON的最簡單方法是什么?

Groovy,就是幾行代碼的問題。 我發現的 Java 個示例長得離譜(並且有巨大的異常處理塊)。

我只想閱讀此鏈接的內容。

使用 Maven 工件org.json:json我得到了以下代碼,我認為它很短。 不是盡可能短,但仍然可用。

package so4308554;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;

import org.json.JSONException;
import org.json.JSONObject;

public class JsonReader {

  private static String readAll(Reader rd) throws IOException {
    StringBuilder sb = new StringBuilder();
    int cp;
    while ((cp = rd.read()) != -1) {
      sb.append((char) cp);
    }
    return sb.toString();
  }

  public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
    InputStream is = new URL(url).openStream();
    try {
      BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
      String jsonText = readAll(rd);
      JSONObject json = new JSONObject(jsonText);
      return json;
    } finally {
      is.close();
    }
  }

  public static void main(String[] args) throws IOException, JSONException {
    JSONObject json = readJsonFromUrl("https://graph.facebook.com/19292868552");
    System.out.println(json.toString());
    System.out.println(json.get("id"));
  }
}

以下是Jackson 的幾個替代版本(因為您可能希望數據的方式不止一種):

  ObjectMapper mapper = new ObjectMapper(); // just need one
  // Got a Java class that data maps to nicely? If so:
  FacebookGraph graph = mapper.readValue(url, FaceBookGraph.class);
  // Or: if no class (and don't need one), just map to Map.class:
  Map<String,Object> map = mapper.readValue(url, Map.class);

特別是您想要處理 Java 對象的通常 (IMO) 情況,可以制作一個班輪:

FacebookGraph graph = new ObjectMapper().readValue(url, FaceBookGraph.class);

其他庫如 Gson 也支持單行方法; 為什么許多示例顯示更長的部分很奇怪。 更糟糕的是,許多示例使用過時的 org.json 庫; 它可能是第一件事,但有六個更好的替代品,因此幾乎沒有理由使用它。

最簡單的方法:使用gson,谷歌自己的goto json 庫。 https://code.google.com/p/google-gson/

這是一個示例。 我要去這個免費的地理定位器網站並解析 json 並顯示我的郵政編碼。 (把這個東西放在一個main方法中測試一下)

    String sURL = "http://freegeoip.net/json/"; //just a string

    // Connect to the URL using java's native library
    URL url = new URL(sURL);
    URLConnection request = url.openConnection();
    request.connect();

    // Convert to a JSON object to print data
    JsonParser jp = new JsonParser(); //from gson
    JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
    JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object. 
    String zipcode = rootobj.get("zip_code").getAsString(); //just grab the zipcode

如果您不介意使用幾個庫,則可以在一行中完成。

包括Apache Commons IOUtilsjson.org庫。

JSONObject json = new JSONObject(IOUtils.toString(new URL("https://graph.facebook.com/me"), Charset.forName("UTF-8")));

Maven 依賴:

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.7</version>
</dependency>

我已經以最簡單的方式完成了 json 解析器,這里是

package com.inzane.shoapp.activity;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser {

static InputStream is = null;
static JSONObject jObj = null;
static String json = "";

// constructor
public JSONParser() {

}

public JSONObject getJSONFromUrl(String url) {

    // Making HTTP request
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
            System.out.println(line);
        }
        is.close();
        json = sb.toString();

    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
        System.out.println("error on parse data in jsonparser.java");
    }

    // return JSON String
    return jObj;

}
}

這個類從 url 返回 json 對象

當你想要 json 對象時,你只需調用這個類和你的 Activity 類中的方法

我的代碼在這里

String url = "your url";
JSONParser jsonParser = new JSONParser();
JSONObject object = jsonParser.getJSONFromUrl(url);
String content=object.getString("json key");

這里的“json key”表示你的json文件中的key

這是一個簡單的 json 文件示例

{
    "json":"hi"
}

這里“json”是鍵,“hi”是值

這將使您的 json 值變為字符串內容。

使用HttpClient抓取 URL 的內容。 然后使用來自json.org的庫來解析 JSON。 我已經在許多項目中使用過這兩個庫,它們非常強大且易於使用。

除此之外,您可以嘗試使用 Facebook API java 庫。 我在這方面沒有任何經驗,但是有一個關於在 java 中使用 Facebook API相關的堆棧溢出的問題。 您可能希望將RestFB視為要使用的庫的不錯選擇。

使用 jersey-client 非常簡單,只需包含此 maven 依賴項:

<dependency>
  <groupId>org.glassfish.jersey.core</groupId>
  <artifactId>jersey-client</artifactId>
  <version>2.25.1</version>
</dependency>

然后使用此示例調用它:

String json = ClientBuilder.newClient().target("http://api.coindesk.com/v1/bpi/currentprice.json").request().accept(MediaType.APPLICATION_JSON).get(String.class);

然后使用谷歌的 Gson 解析 JSON:

Gson gson = new Gson();
Type gm = new TypeToken<CoinDeskMessage>() {}.getType();
CoinDeskMessage cdm = gson.fromJson(json, gm);

我發現這是迄今為止最簡單的方法。

使用這個方法:

public static String getJSON(String url) {
        HttpsURLConnection con = null;
        try {
            URL u = new URL(url);
            con = (HttpsURLConnection) u.openConnection();

            con.connect();


            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            br.close();
            return sb.toString();


        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (con != null) {
                try {
                    con.disconnect();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return null;
    }

並像這樣使用它:

String json = getJSON(url);
JSONObject obj;
   try {
         obj = new JSONObject(json);
         JSONArray results_arr = obj.getJSONArray("results");
         final int n = results_arr.length();
            for (int i = 0; i < n; ++i) {
                // get the place id of each object in JSON (Google Search API)
                String place_id = results_arr.getJSONObject(i).getString("place_id");
            }


   }

我不確定這是否有效,但這是可能的方法之一:

從 url 讀取 json 使用url.openStream()並將內容讀入字符串。

用這個字符串構造一個 JSON 對象(更多信息在json.org

JSONObject(java.lang.String source)
      Construct a JSONObject from a source JSON text string.

這是如何解析 Json 內容的完整示例。 該示例采用 Android 版本統計信息(從此處的Android Studio 源代碼中找到,鏈接到此處)。

將您從那里獲得的“distributions.json”文件復制到 res/raw 中,作為后備。

構建.gradle

    implementation 'com.google.code.gson:gson:2.8.6'

顯現

  <uses-permission android:name="android.permission.INTERNET" />

主活動.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState != null)
            return
        thread {
            // https://cs.android.com/android/platform/superproject/+/studio-master-dev:tools/adt/idea/android/src/com/android/tools/idea/stats/DistributionService.java
            var root: JsonArray
            Log.d("AppLog", "loading...")
            try {
                HttpURLConnection.setFollowRedirects(true)
                val statsUrl = "https://dl.google.com/android/studio/metadata/distributions.json" //just a string
                val url = URL(statsUrl)
                val request: HttpURLConnection = url.openConnection() as HttpURLConnection
                request.connectTimeout = 3000
                request.connect()
                InputStreamReader(request.content as InputStream).use {
                    root = JsonParser.parseReader(it).asJsonArray
                }
            } catch (e: Exception) {
                Log.d("AppLog", "error while loading from Internet, so using fallback")
                e.printStackTrace()
                InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
                    root = JsonParser.parseReader(it).asJsonArray
                }
            }
            val decimalFormat = DecimalFormat("0.00")
            Log.d("AppLog", "result:")

            root.forEach {
                val androidVersionInfo = it.asJsonObject
                val versionNickName = androidVersionInfo.get("name").asString
                val versionName = androidVersionInfo.get("version").asString
                val versionApiLevel = androidVersionInfo.get("apiLevel").asInt
                val marketSharePercentage = androidVersionInfo.get("distributionPercentage").asFloat * 100f
                Log.d("AppLog", "\"$versionNickName\" - $versionName - API$versionApiLevel - ${decimalFormat.format(marketSharePercentage)}%")
            }
        }
    }
}

作為依賴項的替代方案,您也可以使用它:

InputStreamReader(request.content as InputStream).use {
    val jsonArray = JSONArray(it.readText())
}

和后備:

InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
    val jsonArray = JSONArray(it.readText())
}

運行結果如下:

loading...
result:
"Ice Cream Sandwich" - 4.0 - API15 - 0.20%
"Jelly Bean" - 4.1 - API16 - 0.60%
"Jelly Bean" - 4.2 - API17 - 0.80%
"Jelly Bean" - 4.3 - API18 - 0.30%
"KitKat" - 4.4 - API19 - 4.00%
"Lollipop" - 5.0 - API21 - 1.80%
"Lollipop" - 5.1 - API22 - 7.40%
"Marshmallow" - 6.0 - API23 - 11.20%
"Nougat" - 7.0 - API24 - 7.50%
"Nougat" - 7.1 - API25 - 5.40%
"Oreo" - 8.0 - API26 - 7.30%
"Oreo" - 8.1 - API27 - 14.00%
"Pie" - 9.0 - API28 - 31.30%
"Android 10" - 10.0 - API29 - 8.20%

我想在這里添加一個更新的答案,因為(有些)最近對 JDK 的更新使得閱讀 HTTP URL 的內容變得更容易一些。 就像其他人所說的那樣,您仍然需要使用 JSON 庫來進行解析,因為 JDK 當前不包含一個。 以下是一些最常用的 Java JSON 庫:

要從 URL 檢索 JSON,這似乎是嚴格使用 JDK 類的最簡單方法(但可能不是您想要為大型有效負載做的事情),Java 9 引入: https : //docs.oracle.com/en/ java/javase/11/docs/api/java.base/java/io/InputStream.html#readAllBytes()

try(java.io.InputStream is = new java.net.URL("https://graph.facebook.com/me").openStream()) {
    String contents = new String(is.readAllBytes());
}

例如,使用 GSON 庫解析 JSON

com.google.gson.JsonElement element = com.google.gson.JsonParser.parseString(contents); //from 'com.google.code.gson:gson:2.8.6'

Oracle 文檔描述了如何

  1. 構建一個HttpRequest然后
  2. 由 HttpClient 發送到 URL

只需幾行代碼,僅使用 Java Class 庫 將此代碼放入您的主要方法中:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("http://example.com/"))
      .build();
client.sendAsync(request, BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenAccept(System.out::println)
      .join();

響應由 JSON object {... } 組成,可以在您的應用程序中進一步處理。 在這里我將它打印到控制台,只是為了確認它有效:

System.out.println(request);

這適用於 Java 版本 11+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM