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


245

这可能是一个愚蠢的问题,但什么是阅读和分析的最简单方法JSONURL的Java

在Groovy中,只需几行代码即可。我发现Java示例太长了(并且具有巨大的异常处理块)。

我要做的就是阅读此链接的内容。


9
异常处理是必需的,因为java会强制您处理声明的所有异常。异常处理有什么问题?
Falmarri 2010年

3
好吧,“ java强迫你”是最大的问题
Jonatan Cloutier

9
如果Java没有强迫您处理异常,您是否认为程序仍然可以运行并且运行良好?如果要求我将年龄输入程序并输入snarfleblagger作为输入怎么办?Java是否应该允许程序无问题地执行?如果您不想处理异常,则将它们声明为可能发生的方法抛出的异常,并在某些不完全正确的情况下观看程序失败。
理查德·巴克

2
根本不是一个愚蠢的问题。特别是来自PHP的您可以在其中完成此json_decode(file_get_contents($url));工作!
dtbarne

Answers:


193

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

3
您可以在BufferedReader上使用readLine()来代替逐字符读取字符。这将减少while循环的迭代次数。
kdabir

6
做什么的?readLine然后,该函数将执行循环,并且我必须连接行而不是字符,这更昂贵。那不会使代码保持现在那么短。此外,在JSON表示法中没有“线”的概念,那么为什么我应该这样阅读它们呢?
罗兰·伊利格

4
考虑Apache commons-io的IOUtils.toString(InputStream)方法。那应该节省您一些路线和责任。
Mark Tielemans 2013年

3
为什么我在JSONObject行中收到此错误“未定义构造函数JSONObject(String)” json = new JSONObject(jsonText); 在“ readJsonFromUrl”方法中。@RolandIllig
Karthick流行音乐

2
使用GSON,Jackson,Boon,Genson和其他人,您只需提供源:URL或最多InputStream。尽管上面的代码可能org.json用不完,但是请确保验证其他可用的库-无需为此编写多于1-3行的代码。
StaxMan 2015年

68

这是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库。它可能是第一件事,但是有六种更好的选择,因此几乎没有理由使用它。


网址是什么?是字符串,URL对象还是byte []?
Dinesh'3

1
我正想着,java.net.URL但任何一个作品,以及大量的其他来源(FileInputStreamReaderString)。
StaxMan

4
在上面的示例中,它为java.net.URL,否则它将尝试将字符串“ http:// ....”解析为json,这将产生错误
zbstof

@Zotov是的。传递String将要求内容为JSON,而不是要使用的URI / URL的文本编码。
StaxMan'1

2
无法识别的令牌“ https”:正在
等待

60

最简单的方法:使用Google自己的goto json库gson。https://code.google.com/p/google-gson/

这是一个样本。我要去这个免费的geolocator网站,解析json并显示我的邮政编码。(只需将这些内容放入主要方法中进行测试即可)

    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

1
为什么我收到“ NetworkOnMainThreadException”错误?我必须使用AsyncTask还是有另一种方法?在此示例中,您是否也收到此错误?
贝纳兹

错字应该是:rootobj.get("zip_code").getAsString();
loopasam

如何导入jsonParser?我总是收到错误:'错误:(69,9)错误:找不到符号类JsonParser'–
MAESTRO_DE

1
请添加Maven依赖项<dependency> <groupId> com.google.code.gson </ groupId> <artifactId> gson </ artifactId> <version> 2.8.0 </ version> </ dependency>以获得Pom中的JsonParse文件。
sashikanta

可以使用Gson以类型安全的方式进行简化和处理,例如:MyResponseObject response = new GsonBuilder()。create()。fromJson(new InputStreamReader((InputStream)request.getContent()),MyResponseObject.class);
Gregor

42

如果您不介意使用几个库,则可以在一行中完成。

包括Apache Commons IOUtilsjson.org库。

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

您是否对为什么将依赖项添加到gradle会阻止此应用程序安装在我的Google Pixel XL上有任何疑问?
andrdoiddev

@andrdoiddev-您应该单独提出一个问题。它对Apache Commons,Gradle和Android Development更通用。
ezwrighter

1
现在这已经很老了,但是仍然是一个很好的解决方案,以防万一@andrdoiddev或其他任何人仍然需要Gradle依赖项,这些是我正在使用的依赖项:compile group:'org.json',name:'json ”,版本:“ 20180813”,编译组:“ commons-io”,名称:“ commons-io”,版本:“ 2.6”
r02

假设您要触发多个请求,将json响应保存到JSONArray,然后使用FileWriter将JSONArray写入文件,则此库不会对双引号进行转义。这使得文件很容易解析回JSONArray。
Gh0sT


5

我已经以最简单的方式完成了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键”表示您的json文件中的键

这是一个简单的json文件示例

{
    "json":"hi"
}

这里“ json”是键,“ hi”是值

这会将您的json值转换为字符串内容。


1
我认为这不是“简单的方法”
独立

3

使用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);

然后使用Google的Gson解析JSON:

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

没有什么可以解决的,但是球衣客户端软件包的问题太多了……这是一团糟的错误。
Johnny Bigoode17年

我还没有遇到任何问题。您能指出一些细节和/或替代方法吗?
user3892260

我发现的问题与classnotfound错误有关,不确定原因,因为我没有设法解决它。
约翰尼·比古德

3

我发现这是到目前为止最简单的方法。

使用此方法:

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


   }

您那里有一个ClassCastException异常。更改行URL u =新URL(url); 到这个URL u = new URL(null,url,new sun.net.www.protocol.https.Handler()); 此代码工作
阳光明媚的Arya

2

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

从url使用中读取json url.openStream()并将内容读取到字符串中。

使用此字符串构造JSON对象(有关更多信息,请访问json.org

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

0

我想在这里添加一个更新的答案,因为(某种程度上)JDK的最近更新使读取HTTP URL的内容更加容易。就像其他人所说的那样,由于JDK当前不包含JSON库,因此您仍然需要使用JSON库进行解析。以下是一些最常用的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'

0

这是有关如何解析Json内容的完整示例。该示例获取Android版本统计信息(可从Android Studio源代码here找到,该链接链接到here)。

将您从那里获得的“ distributions.json”文件复制到res / raw中,作为后备。

build.gradle

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

表现

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

MainActivity.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%
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.