자바의 URL에서 JSON을 읽는 가장 간단한 방법


245

이 바보 같은 질문이 될 수도 있지만 읽고 분석하는 가장 간단한 방법은 무엇입니까 JSON을 에서 URL자바는 ?

Groovy에서는 몇 줄의 코드 만 필요합니다. 내가 찾은 Java 예제는 엄청나게 길다 (그리고 예외 처리 블록이 크다).

내가하고 싶은 것은 이 링크 의 내용을 읽는 것 입니다.


9
java는 선언 된 예외를 강제로 처리하므로 예외 처리가 필요합니다. 예외 처리에 어떤 문제가 있습니까?
Falmarri

3
"java force you"가 가장 큰 문제입니다
Jonatan Cloutier

9
자바가 예외를 처리하도록 강요하지 않았다면 프로그램이 여전히 잘 실행되고 있다고 생각합니까? 나이를 프로그램에 입력하라는 요청을 받고 snarfleblagger를 입력 한 경우 어떻게합니까? java가 문제없이 프로그램을 실행하도록 허용해야합니까? 예외를 처리하지 않으려면 예외가 발생할 수있는 메소드에 의해 예외가 발생한다고 선언하고 무언가가 완벽하지 않을 때 프로그램이 실패하는 것을 지켜보십시오.
Richard Barker

2
전혀 멍청한 질문이 아닙니다. 특히 PHP를 사용하여이 json_decode(file_get_contents($url));작업을 수행하고 수행 할 수 있습니다 !
dtbarne

답변:


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 표기법에는 "줄"이라는 개념이 없으므로 왜 그렇게 읽어야합니까?
Roland Illig

4
Apache commons-io의 IOUtils.toString(InputStream)방법을 고려하십시오 . 그것은 당신에게 몇 줄과 책임을 저장해야합니다.
Mark Tielemans

3
JSONObject 줄에 "JSONObject (String) 생성자가 정의되어 있지 않습니다"라는 오류가 발생하는 이유는 무엇입니까? json = new JSONObject (jsonText); "readJsonFromUrl"메소드에서 ..? @RolandIllig
Karthick pop

2
GSON, Jackson, Boon, Genson 등을 사용하면 URL 만 또는 최대 소스 만 제공하면됩니다 InputStream. 위의 코드는 org.json사용하기에는 짧을 수 있지만 다른 라이브러리를 사용할 수 있는지 확인하십시오.이 작업을 위해 1-3 줄 이상의 코드를 작성할 필요가 없습니다.
StaxMan

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 라이브러리를 사용한다는 것입니다. 그것은 첫 번째 일 이었을지 모르지만 더 좋은 대안이 6 개이므로 그것을 사용할 이유가 거의 없습니다.


여기 URL은 무엇입니까? 문자열 또는 URL 객체입니까 아니면 바이트 []입니까?
Dinesh

1
내가 생각하고 있었는데 java.net.URL하나 개의 작품뿐만 아니라 다른 소스를 많이하지만, 중 ( File, InputStream, Reader, String).
StaxMan

4
그것은 해야한다 , 그렇지 않으면 구문 분석 문자열을 시도 할 것이다, 위의 예에서 java.net.URL의 수 '에 http : // ...'오류를 얻을 것이다 JSON, 등
zbstof

@Zotov 예. 전달 String하려면 내용이 JSON이어야하고 URI / URL의 텍스트 인코딩이 아니라 야합니다.
StaxMan

2
인식 할 수없는 토큰 'https': 예상 중 ( 'true', 'false'또는 'null')
Damir Olejar

60

가장 쉬운 방법 : Google 자체 goto json 라이브러리 인 gson을 사용하십시오. https://code.google.com/p/google-gson/

다음은 샘플입니다. 이 무료 위치 정보 웹 사이트로 이동하여 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를 사용해야합니까 아니면 다른 방법이 있습니까? 이 예제에서도이 오류가 발생 했습니까?
Benetz

오타 :rootobj.get("zip_code").getAsString();
loopasam

jsonParser를 어떻게 가져 옵니까? 나는 항상 오류 : '오류 : (69, 9) 오류 : 기호 클래스 JsonParser를 찾을 수 없습니다'
MAESTRO_DE

1
pom에 JsonParse를 가져 오려면 maven 종속성 <dependency> <groupId> com.google.code.gson </ groupId> <artifactId> gson </ artifactId> <version> 2.8.0 </ version> </ dependency>을 추가하십시오. 파일.
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 1

@andrdoiddev-별도의 질문으로 요청해야합니다. Apache Commons, Gradle 및 Android 개발이 더 일반적입니다.
ezwrighter

1
이것은 꽤 오래되었지만 여전히 좋은 해결책이므로 @andrdoiddev 또는 다른 사람이 여전히 Gradle 종속성을 필요로하는 경우, 내가 사용하는 것입니다 : compile group : 'org.json', name : 'json ', 버전 :'20180813 '컴파일 그룹 :'commons-io ', 이름 :'commons-io ', 버전 :'2.6 '
r02

여러 요청을 실행하고 JSON 응답을 JSONArray에 저장 한 다음 FileWriter를 사용하여 JSONArray를 파일에 쓰면이 라이브러리는 큰 따옴표를 피하지 않습니다. 이를 통해 파일을 JSONArray로 쉽게 구문 분석 할 수 있습니다.
Gh0sT

6

HttpClient 를 사용 하여 URL의 내용을 가져옵니다. 그런 다음 json.org 의 라이브러리를 사용 하여 JSON을 구문 분석하십시오. 많은 프로젝트에서이 두 라이브러리를 사용했으며 강력하고 사용하기 쉽습니다.

그 외에는 Facebook API Java 라이브러리를 사용해 볼 수 있습니다. 이 분야에 경험이 없지만 java에서 Facebook API사용하는 것과 관련된 스택 오버플로에 대한 질문이 있습니다 . 라이브러리를 사용하기에 좋은 선택으로 RestFB 를보고 싶을 수도 있습니다.


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 key"는 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 Bigoode

나는 아무런 문제가 발생하지 않았습니다. 특정 사항 및 / 또는 대안을 지적 할 수 있습니까?
user3892260

내가 찾은 문제는 classnotfound 오류와 관련이 있습니다. 문제를 해결할 수 없기 때문에 원인에 대해 정확히 확신하지 못했습니다.
Johnny Bigoode

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 = new URL (url); 이 URL로 u = 새 URL (null, url, new sun.net.www.protocol.https.Handler ()); 이 코드가 작동하려면
sunny 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 클래스를 사용하여 간단한 방법이 될 것 같다 (그러나 아마 뭔가 당신이 큰 페이로드에 대해하고 싶은 것), 자바 (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 컨텐츠를 구문 분석하는 방법에 대한 전체 샘플입니다. 이 예는 (안드로이드 스튜디오 소스 코드에서 발견 된 안드로이드 버전의 통계를 취 여기 에 링크를 여기에 ).

거기에서 가져온 "distributions.json"파일을 폴백으로 복사 / 원시로 복사하십시오.

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%
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.