简体   繁体   English

从 Java 中的 URL 读取 JSON 的最简单方法

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

This might be a dumb question but what is the simplest way to read and parse JSON from URL in Java ?这可能是一个愚蠢的问题,但是从Java中的URL读取和解析JSON的最简单方法是什么?

In Groovy, it's a matter of few lines of code. Groovy,就是几行代码的问题。 Java examples that I find are ridiculously long (and have huge exception handling block).我发现的 Java 个示例长得离谱(并且有巨大的异常处理块)。

All I want to do is to read the content of this link .我只想阅读此链接的内容。

Using the Maven artifact org.json:json I got the following code, which I think is quite short.使用 Maven 工件org.json:json我得到了以下代码,我认为它很短。 Not as short as possible, but still usable.不是尽可能短,但仍然可用。

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

Here are couple of alternatives versions with Jackson (since there are more than one ways you might want data as):以下是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);

And specifically the usual (IMO) case where you want to deal with Java objects, can be made one liner:特别是您想要处理 Java 对象的通常 (IMO) 情况,可以制作一个班轮:

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

Other libs like Gson also support one-line methods;其他库如 Gson 也支持单行方法; why many examples show much longer sections is odd.为什么许多示例显示更长的部分很奇怪。 And even worse is that many examples use obsolete org.json library;更糟糕的是,许多示例使用过时的 org.json 库; it may have been the first thing around, but there are half a dozen better alternatives so there is very little reason to use it.它可能是第一件事,但有六个更好的替代品,因此几乎没有理由使用它。

The easiest way: Use gson, google's own goto json library.最简单的方法:使用gson,谷歌自己的goto json 库。 https://code.google.com/p/google-gson/ https://code.google.com/p/google-gson/

Here is a sample.这是一个示例。 I'm going to this free geolocator website and parsing the json and displaying my zipcode.我要去这个免费的地理定位器网站并解析 json 并显示我的邮政编码。 (just put this stuff in a main method to test it out) (把这个东西放在一个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

If you don't mind using a couple libraries it can be done in a single line.如果您不介意使用几个库,则可以在一行中完成。

Include Apache Commons IOUtils & json.org libraries.包括Apache Commons IOUtilsjson.org库。

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

Maven dependency: Maven 依赖:

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

I have done the json parser in simplest way, here it is我已经以最简单的方式完成了 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;

}
}

this class returns the json object from the url这个类从 url 返回 json 对象

and when you want the json object you just call this class and the method in your Activity class当你想要 json 对象时,你只需调用这个类和你的 Activity 类中的方法

my code is here我的代码在这里

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

here the "json key" is denoted that the key in your json file这里的“json key”表示你的json文件中的key

this is a simple json file example这是一个简单的 json 文件示例

{
    "json":"hi"
}

Here "json" is key and "hi" is value这里“json”是键,“hi”是值

This will get your json value to string content.这将使您的 json 值变为字符串内容。

Use HttpClient to grab the contents of the URL.使用HttpClient抓取 URL 的内容。 And then use the library from json.org to parse the JSON.然后使用来自json.org的库来解析 JSON。 I've used these two libraries on many projects and they have been robust and simple to use.我已经在许多项目中使用过这两个库,它们非常强大且易于使用。

Other than that you can try using a Facebook API java library.除此之外,您可以尝试使用 Facebook API java 库。 I don't have any experience in this area, but there is a question on stack overflow related to using a Facebook API in java .我在这方面没有任何经验,但是有一个关于在 java 中使用 Facebook API相关的堆栈溢出的问题。 You may want to look at RestFB as a good choice for a library to use.您可能希望将RestFB视为要使用的库的不错选择。

It's very easy, using jersey-client, just include this maven dependency:使用 jersey-client 非常简单,只需包含此 maven 依赖项:

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

Then invoke it using this example:然后使用此示例调用它:

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

Then use Google's Gson to parse the JSON:然后使用谷歌的 Gson 解析 JSON:

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

I have found this to be the easiest way by far.我发现这是迄今为止最简单的方法。

Use this method:使用这个方法:

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

And use it like this:并像这样使用它:

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


   }

I am not sure if this is efficient, but this is one of the possible ways:我不确定这是否有效,但这是可能的方法之一:

Read json from url use url.openStream() and read contents into a string.从 url 读取 json 使用url.openStream()并将内容读入字符串。

construct a JSON object with this string (more at json.org )用这个字符串构造一个 JSON 对象(更多信息在json.org

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

Here's a full sample of how to parse Json content.这是如何解析 Json 内容的完整示例。 The example takes the Android versions statistics (found from Android Studio source code here , which links to here ).该示例采用 Android 版本统计信息(从此处的Android Studio 源代码中找到,链接到此处)。

Copy the "distributions.json" file you get from there into res/raw, as a fallback.将您从那里获得的“distributions.json”文件复制到 res/raw 中,作为后备。

build.gradle构建.gradle

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

manifest显现

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

MainActivity.kt主活动.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)}%")
            }
        }
    }
}

As alternative to the dependency, you can also use this instead:作为依赖项的替代方案,您也可以使用它:

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

and the fallback:和后备:

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

The result of running this:运行结果如下:

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%

I wanted to add an updated answer here since (somewhat) recent updates to the JDK have made it a bit easier to read the contents of an HTTP URL.我想在这里添加一个更新的答案,因为(有些)最近对 JDK 的更新使得阅读 HTTP URL 的内容变得更容易一些。 Like others have said, you'll still need to use a JSON library to do the parsing, since the JDK doesn't currently contain one.就像其他人所说的那样,您仍然需要使用 JSON 库来进行解析,因为 JDK 当前不包含一个。 Here are a few of the most commonly used JSON libraries for Java:以下是一些最常用的 Java JSON 库:

To retrieve JSON from a URL, this seems to be the simplest way using strictly JDK classes (but probably not something you'd want to do for large payloads), Java 9 introduced: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#readAllBytes()要从 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());
}

To parse the JSON using the GSON library, for example例如,使用 GSON 库解析 JSON

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

The Oracle Documentation describes how Oracle 文档描述了如何

  1. an HttpRequest is built and then构建一个HttpRequest然后
  2. sent by the HttpClient to the URL由 HttpClient 发送到 URL

in just a few lines of code, by using only the Java Class Library .只需几行代码,仅使用 Java Class 库 Put this code into your main method:将此代码放入您的主要方法中:

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();

The response consists of a JSON object {... } and can be further processed in your application.响应由 JSON object {... } 组成,可以在您的应用程序中进一步处理。 Here I printed it to the console, just to confirm it works:在这里我将它打印到控制台,只是为了确认它有效:

System.out.println(request);

This is available for Java Versions 11+这适用于 Java 版本 11+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM