날씨 api 연동하기(JSON, Java)

oh_eol·2022년 3월 1일
0

2021 학부연구생

목록 보기
3/6
post-thumbnail

OpenWeather API : Hourly Forecast 2 days

One Call API

참고 사이트

  • api 사용

[JAVA] Open 날씨 API

  • UNIX Timestamp 변환

Java 자바 UNIX Timestamp 변환 timestamp to date String

1. 설정

  • java에서 json 데이터를 다루기 위해서 json-simple 이용.

Code

[이클립스] JAVA 프로젝트에 라이브러리(.jar) 추가 하는 방법

2. 1차 코드(2021.08.05)

  • 현재 시간과 특정 시간을 골라서 날씨를 받아올 수 있도록 함.
package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Date;
import java.text.SimpleDateFormat;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.util.Scanner;

public class WeatherApp {
	public static void main(String[] args) {
		try {
			// 한신대학교의 위도와 경도
			String lat = "37.193542"; // 위도
			String lon = "127.022556"; // 경도

			// 제외하고 싶은 데이터
			String[] part = { "current", "minutely", "hourly", "daily", "alerts" };

			// OpenAPI call하는 URL
			String urlstr = "https://api.openweathermap.org/data/2.5/onecall?"
					+ "lat=" + lat + "&lon=" + lon + "&lang=kr&exclude=" + part[1]
					+ "," + part[4] + "&appid=1eb1d18602c0e2dde562cdc2005a4495";
			URL url = new URL(urlstr);
			BufferedReader bf;
			String line;
			String result = "";

			// openStream 메소드로 날씨 정보를 받아온다.
			bf = new BufferedReader(new InputStreamReader(url.openStream()));

			// 버퍼에 있는 정보를 문자열로 변환.
			while ((line = bf.readLine()) != null) {
				result = result.concat(line);
				// 받아온 데이터를 확인.
				System.out.println(result);
			}

			// 문자열을 JSON으로 파싱
			// 오류 1
			// JSONParser
			JSONParser jsonParser = new JSONParser();
			// To JSONObject
			JSONObject jsonObj = (JSONObject) jsonParser.parse(result);

			Scanner sc = new Scanner(System.in);
			System.out.println("1. 현재 날씨 조회\t2. 특정 시간 날씨 조회");
			int k = sc.nextInt();

			// 현재 날씨
			if (k == 1) {
				// 위치 출력
				System.out.println("위도 : " + jsonObj.get("lat") + "경도 : " + jsonObj.get("lon"));

				// 날짜 및 시간 출력
				Object timeObj = jsonObj.get("current.dt");
				String str = String.valueOf(timeObj);
				// System.out.println(str);  결과: null 로 나옴.
				String dateStr = getTimestampToDate(str);
				System.out.println("현재 시간: " + dateStr);

				// 날씨 출력
				JSONArray weatherArray = (JSONArray) jsonObj.get("current.weather");
				JSONObject WeatherObj = (JSONObject) weatherArray.get(0);
				System.out.println("날씨 : " + WeatherObj.get("description"));

				// 온도, 습도, 풍속 출력
				JSONObject mainArray = (JSONObject) jsonObj.get("current");
				double ktemp = Double.parseDouble(mainArray.get("temp").toString());
				double temp = ktemp - 273.15;
				int humidity = Integer.parseInt(mainArray.get("humidity").toString());
				int windSpeed = Integer.parseInt(mainArray.get("wind_speed").toString());
				System.out.printf("온도 : %.2f°C\n습도 : %d%\n풍속 : %.2fm/s", temp, humidity, windSpeed);
			}
			// 특정 시간의 날씨
			else if (k == 2) {

				System.out.println("몇 시의 날씨를 조회하겠습니까?(금일로부터 48시간 이내: 1~48)");
				int i = sc.nextInt();

				JSONArray f_WeatherArray = (JSONArray) jsonObj.get("hourly");
				JSONObject f_WeatherObj = (JSONObject) f_WeatherArray.get(i);

				// 날짜 및 시간 출력
				Object timeObj_h = f_WeatherObj.get("dt");
				String str_h = String.valueOf(timeObj_h);
				String dateStr_h = getTimestampToDate(str_h);
				System.out.println("시간: " + dateStr_h);

				// 미래 날씨 출력
				JSONArray f_weatherArray_w = (JSONArray) f_WeatherObj.get("weather");
				JSONObject f_WeatherObj_w = (JSONObject) f_weatherArray_w.get(i);
				System.out.println("날씨 : " + f_WeatherObj_w.get("description"));

				// 미래 온도, 습도, 풍속 출력
				// JSONObject mainArray_hour = (JSONObject) jsonObj.get("hourly");
				double ktemp_h = Double.parseDouble(f_WeatherObj.get("temp").toString());
				double temp_h = ktemp_h - 273.15;
				int humidity_h = Integer.parseInt(f_WeatherObj.get("humidity").toString());
				int windSpeed_h = Integer.parseInt(f_WeatherObj.get("wind_speed").toString());
				System.out.printf("온도 : %.2f°C\n습도 : %d%\n풍속 : %.2fm/s", temp_h, humidity_h, windSpeed_h);
			}

			bf.close();

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	// unix timestamp to date String
	private static String getTimestampToDate(String timestampStr) {
		long timestamp = Long.parseLong(timestampStr);
		Date date = (Date) new java.util.Date(timestamp * 1000L);
		SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
		String formattedDate = sdf.format(date);
		return formattedDate;
	}

}
  • 실행창

  • 대체 코드
    - json-simple 이용 말고 java.net.URL 사용
    - 처음에 계속 오류가 나서 위의 2번으로 사용했는데 다시 시도하니 정상 작동
    - 시간이 부족해서 기타 부분은 구현을 못 함

    package test;
    
    import java.net.URL;
    import java.net.URLConnection;
    import java.net.MalformedURLException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.BufferedReader;
    import java.io.IOException;
    
    public class WeatherURL{
      public static void main(String args[]){
    
          URL url;//URL 주소 객체
          URLConnection connection;//URL접속을 가지는 객체
          InputStream is;//URL접속에서 내용을 읽기위한 Stream
          InputStreamReader isr;
          BufferedReader br;
    
          try{
              //URL객체를 생성하고 해당 URL로 접속한다.
              url = new URL("https://api.openweathermap.org/data/2.5/onecall?lat=37.193542&lon=127.022556&exclude=minutely,alerts&appid=1eb1d18602c0e2dde562cdc2005a4495");
              connection = url.openConnection();
              //내용을 읽어오기위한 InputStream객체를 생성한다.
              is = connection.getInputStream();
              isr = new InputStreamReader(is);
              br = new BufferedReader(isr);
    
              //내용을 읽어서 화면에 출력한다.
              String buf = null;
              while(true){
                  buf = br.readLine();
                  if(buf == null) break;
                  System.out.println(buf);
                  int a2 = buf.indexOf("temp");
                  double temp=Double.parseDouble(buf.substring(a2+6, a2+12))-273.15;
                  System.out.println("서울의 현재 온도(섭씨):"+temp);
              }
          }catch(MalformedURLException mue){
              System.err.println("잘못된 URL입니다.");
              System.exit(1);
          }catch(IOException ioe){
              System.err.println("IOException " + ioe);
              ioe.printStackTrace();
              System.exit(1);
          }
      }
    }

3. 2차 코드(2021.08.12)

package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.net.URLEncoder;
import java.net.http.HttpResponse;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.util.Scanner;

import javax.net.ssl.HttpsURLConnection;

public class WeatherApp {
	public static void main(String[] args) throws Exception {
		
		try {
			Scanner sc = new Scanner(System.in);
			String x = null;
			String y = null;
			
			//	현재 위치를 입력받아서 getCoordination 메소드를 통해서 JSON 데이터를 가져온다.
			System.out.print("현재 위치를 입력하세요 : ");
			String address = sc.nextLine();
			String jsonStr = getCoordination(address);
			
			//	가져온 JSON 데이터를 파싱하여 위도 경도를 각각 y, x 변수로 저장.
			JSONObject json = ( JSONObject ) new JSONParser().parse( jsonStr );
			JSONArray jsonDocuments = (JSONArray) json.get( "documents" );
			if( jsonDocuments.size() != 0 ) {
				JSONObject j = (JSONObject) jsonDocuments.get(0);
				y = ( String ) j.get( "y" );
				x = ( String ) j.get( "x" );
			} 
			
			//	입력받은 위치의 위도와 경도
			String lat = y; // 위도
			String lon = x; // 경도
			// System.out.println("위도: "+lat+"\t경도: "+lon);
			
			// 제외하고 싶은 데이터
			String[] part = { "current", "minutely", "hourly", "daily", "alerts" };

			// OpenAPI call하는 URL
			String urlstr = "https://api.openweathermap.org/data/2.5/onecall?" + "lat=" + lat + "&lon=" + lon
					+ "&lang=kr&exclude=" + part[1] + "," + part[4] + "&appid=1eb1d18602c0e2dde562cdc2005a4495";
			URL url = new URL(urlstr);
			BufferedReader bf;
			String line;
			String result = "";

			// 날씨 정보를 받아온다.
			bf = new BufferedReader(new InputStreamReader(url.openStream()));

			// 버퍼에 있는 정보를 문자열로 변환.
			while ((line = bf.readLine()) != null) {
				result = result.concat(line);
				// 받아온 데이터를 확인.
				// System.out.println(result);
			}

			// 문자열을 JSON으로 파싱
			// JSONParser
			JSONParser jsonParser = new JSONParser();
			// To JSONObject
			JSONObject jsonObj = (JSONObject) jsonParser.parse(result);

			
			
			System.out.println("1. 현재 날씨 조회\t2. 특정 시간 날씨 조회");
			int k = sc.nextInt();

			// 현재 날씨
			if (k == 1) {
				// 위치 출력
				System.out.println("위도 : " + jsonObj.get("lat") + "\t경도 : " + jsonObj.get("lon"));
				
				// 날짜 및 시간 출력
				// 오류 2
				// 출력 결과 null값이 나옴.
				System.out.println("UNIX 시간: " + jsonObj.get("current.dt"));
				//	값 존재 여부 확인
				if(jsonObj.get("current.dt").equals(null)) {
					System.out.println("currnet not has");
				} else {
					System.out.println("current has");
				}
				
				String str = String.valueOf(jsonObj.get("current.dt"));
				String dateStr = getTimestampToDate(str);
				System.out.println("현재 시간: " + dateStr);

				// 날씨 출력
				System.out.println("날씨 : " + jsonObj.get("description"));

				// 온도, 습도, 풍속 출력
				double ktemp = Double.parseDouble(jsonObj.get("temp").toString());
				double temp = ktemp - 273.15;
				int humidity = Integer.parseInt(jsonObj.get("humidity").toString());
				int windSpeed = Integer.parseInt(jsonObj.get("windSpeed").toString());
				System.out.printf("온도 : %.2f°C\n습도 : %d%\n풍속 : %.2fm/s", temp, humidity, windSpeed);
			}
			// 특정 시간의 날씨
			else if (k == 2) {

				System.out.println("몇 시의 날씨를 조회하겠습니까?(금일로부터 48시간 이내: 1~48)");
				int i = sc.nextInt();

				JSONArray f_WeatherArray = (JSONArray) jsonObj.get("hourly");
				JSONObject f_WeatherObj = (JSONObject) f_WeatherArray.get(i);

				// 날짜 및 시간 출력
				Object timeObj_h = f_WeatherObj.get("dt");
				String str_h = String.valueOf(timeObj_h);
				String dateStr_h = getTimestampToDate(str_h);
				System.out.println("시간: " + dateStr_h);

				// 미래 날씨 출력
				JSONArray f_weatherArray_w = (JSONArray) f_WeatherObj.get("weather");
				JSONObject f_WeatherObj_w = (JSONObject) f_weatherArray_w.get(i);
				System.out.println("날씨 : " + f_WeatherObj_w.get("description"));

				// 미래 온도, 습도, 풍속 출력
				// JSONObject mainArray_hour = (JSONObject) jsonObj.get("hourly");
				double ktemp_h = Double.parseDouble(f_WeatherObj.get("temp").toString());
				double temp_h = ktemp_h - 273.15;
				int humidity_h = Integer.parseInt(f_WeatherObj.get("humidity").toString());
				int windSpeed_h = Integer.parseInt(f_WeatherObj.get("wind_speed").toString());
				System.out.printf("온도 : %.2f°C\n습도 : %d%\n풍속 : %.2fm/s", temp_h, humidity_h, windSpeed_h);
			}

			bf.close();

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	// unix timestamp to date String
	private static String getTimestampToDate(String timestampStr) {
		// long timestamp = Long.parseLong(timestampStr);
		long timestamp = 0;
		try {

			System.out.println("er");
			timestamp = Long.parseLong(timestampStr);
			System.out.println("errrr");
			System.out.println(timestamp);
		} catch (Exception e) {
			System.out.println("The input string does not represent a valid number");
		}

		Date date = (Date) new java.util.Date(timestamp * 1000L);
		SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
		String formattedDate = sdf.format(date);

		return formattedDate;
	}

	//	kakao maps api JSON 데이터 가져오기
	private static String getCoordination( String address ) throws Exception {
		
		String encodeAddress = "";  // 한글 주소는 encoding 해서 날려야 함
		try {
			//	URLEncoder.encode 공백처리 문제로 400 오류 발생 가능해서 .replaceAll("\\+","%20") 을 붙여야? ㅇ... 일단 해보고 테스트 
			encodeAddress = URLEncoder.encode( address, "UTF-8" );
			} 
		catch ( UnsupportedEncodingException e ) {
			e.printStackTrace();
			}
		
		String apiUrl = "https://dapi.kakao.com/v2/local/search/address.json?query=" + encodeAddress;
		String auth = "KakaoAK 91ee832ce89440155c14ad98c1de0f74";
		
		URL url = new URL( apiUrl );
	    HttpsURLConnection conn = ( HttpsURLConnection ) url.openConnection();
		conn.setRequestMethod( "GET" );
	    conn.setRequestProperty( "Authorization", auth );
	    
	    BufferedReader br;

	    int responseCode = conn.getResponseCode();
	    if( responseCode == 200 ) {  // 호출 OK
	    	br = new BufferedReader( new InputStreamReader(conn.getInputStream(), "UTF-8") );
	    } else {  // 에러
	    	br = new BufferedReader( new InputStreamReader(conn.getErrorStream(), "UTF-8") );
	    }
	    
	    String jsonString = new String();
	    String stringLine;
	    while ( ( stringLine= br.readLine()) != null ) {
	        jsonString += stringLine;
	    }
	    return jsonString;
	}
	
}
  • 오류 2
    • 좌표를 찍어서 오류 난 부분을 확인해보니 String dateStr = getTimestampToDate(str); 이 부분에서 오류가 남. 메소드에서 또 좌표를 찍어서 확인하니 String 타입을 long 타입으로 바꾸는 long timestamp = Long.parseLong(timestampStr); 여기서 난 오류로 확인됨.
    • String str2 = "1628717571"; 을 새로 선언해서 getTimestampToDate(str2); 를 실행했을 때에는 StringToLong 타입 변환이 정상적으로 이루어짐.
    • 그래서 current.dt 값을 확인하고자 출력해보니 null 값이 나옴. current 안의 모든 값이 null 값이 나오는 것으로 추정되어 정확하게 확인하고자 .equal(null) 을 사용하여 값 존재여부를 확인하니 아래와 같은 오류 나옴.

현재 위치를 자동으로 가져오게 하는 API

지금은 현재 주소를 입력하면 그에 따른 좌표값을 구할 수 있도록 함.

위치를 입력하지 않고 자동으로 가져오게 하는 API를 Java에서는 찾지 못했는데 JavaScript에는 geolocation 이라는 API가 존재.

사용하는 기기의 gps 및 wifi로 현재 위치를 가져오는 api

#4 Geolocation API로 현재 위치 가져오기

profile
공부 중입니다.

0개의 댓글