날씨 api 연동하기

oh_eol·2022년 3월 1일
1

2021 학부연구생

목록 보기
4/6
post-thumbnail

코드

  • current data 등 null값 나오던 문제 해결
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] + "&units=metric&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"));

                //  경기도 오산시 양산동 한신대길 127
//                // 날짜 및 시간 출력
                JSONObject currentArr = (JSONObject) jsonObj.get("current");
                String dt = currentArr.get("dt").toString();
                String dateStr = getTimestampToDate(dt);
                System.out.println("현재 시간: " + dateStr);

//                // 온도, 습도, 풍속 출력
                String temp = currentArr.get("temp").toString();
                System.out.println("현재 온도: " + temp);
                String humidity = currentArr.get("humidity").toString();
                System.out.println("현재 습도: " + humidity);
                String wind_speed = currentArr.get("wind_speed").toString();
                System.out.println("현재 풍속: " + wind_speed);

                // 날씨 출력
//                JSONObject cuWeatherArr = (JSONObject) jsonObj.get("weather");
//                String desc = cuWeatherArr.get("description").toString();
                JSONArray cuWeatherArr = (JSONArray) jsonObj.get("weather");
                JSONObject cuWeatherObj = (JSONObject) cuWeatherArr.get(0);

                Object timeObj_h = cuWeatherObj.get("description");
                String desc = String.valueOf(timeObj_h);
                System.out.println("날씨: " + desc);

            }
            // 특정 시간의 날씨
            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 = 0;
        try {
            timestamp = Long.parseLong(timestampStr);
            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;
    }
}

오류

  1. 오류

    현재 시간 출력 시 unix → date 타입 변환이 잘 이뤄지지 않고 unix가 그대로 출력됨.

    미해결

  2. 오류

    다른 값들은 출력이 잘 되지만 배열 안의 값에 접근하는데 오류가 나서 null 값으로 뜸.

    미해결

데이터 단위

  • Fields in API response
    • lat Geographical coordinates of the location (latitude)
    • lon Geographical coordinates of the location (longitude)
    • timezone Timezone name for the requested location
    • timezone_offset Shift in seconds from UTC
    • current Current weather data API response
      • current.dt Current time, Unix, UTC
      • current.sunrise Sunrise time, Unix, UTC
      • current.sunset Sunset time, Unix, UTC
      • current.temp Temperature. Units - default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used
      • current.feels_like Temperature. This temperature parameter accounts for the human perception of weather. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit.
      • current.pressure Atmospheric pressure on the sea level, hPa
      • current.humidity Humidity, %
      • current.dew_point Atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit.
      • current.clouds Cloudiness, %
      • current.uvi Current UV index
      • current.visibility Average visibility, metres
      • current.wind_speed Wind speed. Wind speed. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used
      • current.wind_gust (where available) Wind gust. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used
      • current.wind_deg Wind direction, degrees (meteorological)
      • current.rain
        • current.rain.1h (where available) Rain volume for last hour, mm
      • current.snow
        • current.snow.1h (where available) Snow volume for last hour, mm
      • current.weather
    • minutely Minute forecast weather data API response
      • minutely.dt Time of the forecasted data, unix, UTC
      • minutely.precipitation Precipitation volume, mm
    • hourly Hourly forecast weather data API response
      • hourly.dt Time of the forecasted data, Unix, UTC
      • hourly.temp Temperature. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used
      • hourly.feels_like Temperature. This accounts for the human perception of weather. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit.
      • hourly.pressure Atmospheric pressure on the sea level, hPa
      • hourly.humidity Humidity, %
      • hourly.dew_point Atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit.
      • hourly.uvi UV index
      • hourly.clouds Cloudiness, %
      • hourly.visibility Average visibility, metres
      • hourly.wind_speed Wind speed. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour.How to change units used
      • hourly.wind_gust (where available) Wind gust. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used
      • chourly.wind_deg Wind direction, degrees (meteorological)
      • hourly.pop Probability of precipitation
      • hourly.rain
        • hourly.rain.1h (where available) Rain volume for last hour, mm
      • hourly.snow
        • hourly.snow.1h (where available) Snow volume for last hour, mm
      • hourly.weather
    • daily Daily forecast weather data API response
      • daily.dt Time of the forecasted data, Unix, UTC
      • daily.sunrise Sunrise time, Unix, UTC
      • daily.sunset Sunset time, Unix, UTC
      • daily.moonrise The time of when the moon rises for this day, Unix, UTC
      • daily.moonset The time of when the moon sets for this day, Unix, UTC
      • daily.moon_phase Moon phase. 0 and 1 are 'new moon', 0.25 is 'first quarter moon', 0.5 is 'full moon' and 0.75 is 'last quarter moon'. The periods in between are called 'waxing crescent', 'waxing gibous', 'waning gibous', and 'waning crescent', respectively.
      • daily.temp Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used
        • daily.temp.morn Morning temperature.
        • daily.temp.day Day temperature.
        • daily.temp.eve Evening temperature.
        • daily.temp.night Night temperature.
        • daily.temp.min Min daily temperature.
        • daily.temp.max Max daily temperature.
      • daily.feels_like This accounts for the human perception of weather. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit. How to change units used
        • daily.feels_like.morn Morning temperature.
        • daily.feels_like.day Day temperature.
        • daily.feels_like.eve Evening temperature.
        • daily.feels_like.night Night temperature.
      • daily.pressure Atmospheric pressure on the sea level, hPa
      • daily.humidity Humidity, %
      • daily.dew_point Atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. Units – default: kelvin, metric: Celsius, imperial: Fahrenheit.
      • daily.wind_speed Wind speed. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used
      • daily.wind_gust (where available) Wind gust. Units – default: metre/sec, metric: metre/sec, imperial: miles/hour. How to change units used
      • daily.wind_deg Wind direction, degrees (meteorological)
      • daily.clouds Cloudiness, %
      • daily.uvi The maximum value of UV index for the day
      • daily.pop Probability of precipitation
      • daily.rain (where available) Precipitation volume, mm
      • daily.snow (where available) Snow volume, mm
      • daily.weather
    • alerts National weather alerts data from major national weather warning systems
      • alerts.sender_name Name of the alert source. Please read here the full list of alert sources
      • alerts.event Alert event name
      • alerts.start Date and time of the start of the alert, Unix, UTC
      • alerts.end Date and time of the end of the alert, Unix, UTC
      • alerts.description Description of the alert
      • alerts.tags Type of severe weather
profile
공부 중입니다.

0개의 댓글