简体   繁体   English

使用 Openweather API 获取特定日期的天气 - 解析 JSON 响应

[英]Get weather for specific date using Openweather API - parsing JSON response

I am trying to build a simple weather forecasting app using Android studio and Java.我正在尝试使用 Android studio 和 Java 构建一个简单的天气预报应用程序。 I followed some instructions here ( https://www.androdocs.com/java/creating-an-android-weather-app-using-java.html ) to get up and running and this works.我按照这里的一些说明( https://www.androdocs.com/java/creating-an-android-weather-app-using-java.html )启动并运行,这很有效。 However, I can only get the current weather.但是,我只能得到当前的天气。 Openweather forecasting API calls seem to be for 5 days. Openweather 预报 API 电话似乎是 5 天。 That's ok, but how do I get the weather - say temp and wind speed - for a specific date specified by the user that's within the next 5 days?没关系,但是我如何获取用户指定的未来 5 天内的特定日期的天气(比如温度和风速)?

Below is a sample JSON response (shortened).下面是一个示例 JSON 响应(缩短)。 Even if I could pull out the info around a specific date at 12pm, and get the temp and wind speed for that date, that would be enough.即使我可以在下午 12 点提取特定日期的信息,并获得该日期的温度和风速,也足够了。 How do I parse this JSON response to get the temp and wind speed for a specific date?如何解析此 JSON 响应以获取特定日期的温度和风速? Thanks so much... sorry I'm a beginner...非常感谢...对不起我是初学者...

{"cod":"200","message":0,"cnt":40,"list":[{"dt":1574283600,"main":{"temp":281.75,"temp_min":281.68,"temp_max":281.75,"pressure":995,"sea_level":995,"grnd_level":980,"humidity":93,"temp_kf":0.07},"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":4.82,"deg":147},"rain":{"3h":5.38},"sys":{"pod":"n"},"dt_txt":"2019-11-20 21:00:00"},{"dt":1574294400,"main":{"temp":281.79,"temp_min":281.74,"temp_max":281.79,"pressure":995,"sea_level":995,"grnd_level":980,"humidity":91,"temp_kf":0.05},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":5.55,"deg":140},"rain":{"3h":1.75},"sys":{"pod":"n"},"dt_txt":"2019-11-21 00:00:00"},{"dt":1574305200,"main":{"temp":279.48,"temp_min":279.44,"temp_max":279.48,"pressure":994,"sea_level":994,"grnd_level":980,"humidity":95,"temp_kf":0.04},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"clouds":{"all":100}, {"cod":"200","message":0,"cnt":40,"list":[{"dt":1574283600,"main":{"temp":281.75,"temp_min":281.68, "temp_max":281.75,"压力":995,"sea_level":995,"grnd_level":980,"湿度":93,"temp_kf":0.07},"天气":[{"id":501," main":"Rain","description":"中雨","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":4.82,"度":147},"雨":{"3h":5.38},"sys":{"pod":"n"},"dt_txt":"2019-11-20 21:00:00"}, {"dt":1574294400,"main":{"temp":281.79,"temp_min":281.74,"temp_max":281.79,"pressure":995,"sea_level":995,"grnd_level":980,"湿度":91,"temp_kf":0.05},"weather":[{"id":500,"main":"Rain","description":"小雨","icon":"10n"}], "clouds":{"all":100},"wind":{"speed":5.55,"deg":140},"rain":{"3h":1.75},"sys":{"pod" :"n"},"dt_txt":"2019-11-21 00:00:00"},{"dt":1574305200,"main":{"temp":279.48,"temp_min":279.44,"temp_max ":279.48,"压力":994,"sea_level":994,"grnd_level":980,"湿度":95,"temp_kf":0.04},"天气":[{"id":500,"main" :"Rain","description":"小雨","icon":"10n"}],"clouds":{"all":100}, "wind":{"speed":2.37,"deg":155},"rain":{"3h":0.94},"sys":{"pod":"n"},"dt_txt":"2019-11-21 03:00:00"},{"dt":1574316000,"main":{"temp":278.56,"temp_min":278.54,"temp_max":278.56,"pressure":995,"sea_level":995,"grnd_level":980,"humidity":94,"temp_kf":0.02},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":1.73,"deg":128},"rain":{"3h":0.06},"sys":{"pod":"n"},"dt_txt":"2019-11-21 06:00:00"},{"dt":1574326800,"main":{"temp":279.19,"temp_min":279.19,"temp_max":279.19,"pressure":995,"sea_level":995,"grnd_level":981,"humidity":95,"temp_kf":0},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"clouds":{"all":100},"wind":{"speed":1.79,"deg":104},"sys":{"pod":"d"},"dt_txt":"2019-11-21 09:00:00"},{"dt":1574337600,"main":{"temp":282.2,"temp_min":282.2,"temp_max":282.2,"pressure":995,"sea_level":995,"grnd_level":980,"humidity":85,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"light rain"," "风":{"速度":2.37,"deg":155},"雨":{"3h":0.94},"sys":{"pod":"n"},"dt_txt":"2019 -11-21 03:00:00"},{"dt":1574316000,"main":{"temp":278.56,"temp_min":278.54,"temp_max":278.56,"pressure":995,"sea_level ":995,"grnd_level":980,"湿度":94,"temp_kf":0.02},"weather":[{"id":500,"main":"Rain","description":"小雨","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":1.73,"deg":128},"rain":{"3h" :0.06},"sys":{"pod":"n"},"dt_txt":"2019-11-21 06:00:00"},{"dt":1574326800,"main":{"temp ":279.19,"temp_min":279.19,"temp_max":279.19,"压力":995,"sea_level":995,"grnd_level":981,"湿度":95,"temp_kf":0},"天气" :[{"id":804,"main":"Clouds","description":"阴云","icon":"04d"}],"clouds":{"all":100},"wind ":{"speed":1.79,"deg":104},"sys":{"pod":"d"},"dt_txt":"2019-11-21 09:00:00"},{" dt":1574337600,"main":{"temp":282.2,"temp_min":282.2,"temp_max":282.2,"pressure":995,"sea_level":995,"grnd_level":980,"湿度": 85,"temp_kf":0},"weather":[{"id":500,"main":"Rain","description":"小雨"," icon":"10d"}],"clouds":{"all":100},"wind":{"speed":2.78,"deg":129},"rain":{"3h":0.19},"sys":{"pod":"d"},"dt_txt":"2019-11-21 12:00:00"} icon":"10d"}],"clouds":{"all":100},"wind":{"speed":2.78,"deg":129},"rain":{"3h":0.19} ,"sys":{"pod":"d"},"dt_txt":"2019-11-21 12:00:00"}

JSON-Simple JSON-简单

Here is an example app using the JSON-Simple library to parse the JSON data downloaded from OpenWeatherMap.org .这是一个使用JSON-Simple库解析从OpenWeatherMap.org下载的 JSON 数据的示例应用程序。

package work.basil.example;

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

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Weather
{

    public static void main ( String[] args )
    {

        Weather app = new Weather();
        app.demo();
    }

    private void demo ( )
    {
        //Creating a JSONParser object
        JSONParser jsonParser = new JSONParser();
        try
        {
            // Download JSON.
            String yourKey = "b6907d289e10d714a6e88b30761fae22";
            URL url = new URL( "https://samples.openweathermap.org/data/2.5/forecast/hourly?zip=79843&appid=b6907d289e10d714a6e88b30761fae22" + yourKey ); // 79843 = US postal Zip Code for Marfa, Texas.
            URLConnection conn = url.openConnection();
            BufferedReader reader = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );


            // Parse JSON
            JSONObject jsonObject = ( JSONObject ) jsonParser.parse( reader );
            System.out.println( "jsonObject = " + jsonObject );

            JSONArray list = ( JSONArray ) jsonObject.get( "list" );
            System.out.println( "list = " + list );

            // Loop through each item
            for ( Object o : list )
            {
                JSONObject forecast = ( JSONObject ) o;

                Long dt = ( Long ) forecast.get( "dt" );          // Parse text into a number of whole seconds.
                Instant instant = Instant.ofEpochSecond( dt );    // Parse the count of whole seconds since 1970-01-01T00:00Z into a `Instant` object, representing a moment in UTC with a resolution of nanoseconds.
                ZoneId z = ZoneId.of( "America/Chicago" );        // Specify a time zone using a real `Continent/Region` time zone name. Never use 2-4 letter pseudo-zones such as `PDT`, `CST`, `IST`, etc.
                ZonedDateTime zdt = instant.atZone( z );          // Adjust from a moment in UTC to the wall-clock used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
                LocalTime lt = zdt.toLocalTime() ;
                // … compare with lt.equals( LocalTime.NOON ) to find the data sample you desire. 
                System.out.println( "dt : " + dt );
                System.out.println( "instant : " + instant );
                System.out.println( "zdt : " + zdt );

                JSONObject main = ( JSONObject ) forecast.get( "main" );
                System.out.println( "main = " + main );


                Double temp = ( Double ) main.get( "temp" );  // Better to use BigDecimal instead of Double for accuracy. But I do not know how to get the JSON-Simple library to parse the original string input as a BigDecimal.
                System.out.println( "temp = " + temp );

                JSONObject wind = ( JSONObject ) forecast.get( "wind" );
                System.out.println( "wind = " + wind );

                System.out.println( "BASIL - wind.getCLass: " + wind.getClass() );
                Double speed = ( Double ) wind.get( "speed" );
                System.out.println( "speed = " + speed );

                System.out.println( "\n" );
            }
        }
        catch ( FileNotFoundException e )
        {
            e.printStackTrace();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        catch ( ParseException e )
        {
            e.printStackTrace();
        }
    }
}

Decimal separator小数分隔符

Notice that this code blows up when encountering a wind speed data point lacking the decimal separator.请注意,当遇到缺少小数点分隔符的风速数据点时,此代码会崩溃。 The publisher of that data should be writing, for example, 1.0 rather than 1 for consistency.例如,该数据的发布者应该写入1.0而不是1以保持一致性。 If they had done so, the library would have parsed 1.0 as a Double rather than parsing 1 as Long .如果他们这样做了,库会将1.0解析为Double而不是将1解析为Long

JSON-Simple 1 now defunct JSON-Simple 1现已失效

Also this code uses the original version 1 of JSON-Simple, now defunct.此代码还使用 JSON-Simple 的原始版本 1,现已失效。 This project was forked, producing dramatically different versions 2 & 3.这个项目是分叉的,产生了截然不同的版本 2 和 3。

See this page Parsing decimal numbers, some of which lack a decimal separator, in JSON data using JSON-Simple (Java) for details about the parsing-decimal problem and about links to the forked project .请参阅此页面使用 JSON-Simple (Java) 在 JSON 数据中解析十进制数字,其中一些缺少小数分隔符,以获取有关解析十进制问题和分叉项目链接的详细信息。

Not for production use不用于生产用途

So while I would not recommend this code for production use , it may help you along the way.因此,虽然我不建议将此代码用于生产用途,但它可能会对您有所帮助。 For real work, consider the later version 3 of JSON-Simple or any of the several other JSON-processing libraries available for Java.对于实际工作,请考虑 JSON-Simple 的更高版本 3 或可用于 Java 的其他几个 JSON 处理库中的任何一个。

See the example data at this URL .请参阅此 URL中的示例数据。 To make it readable, use your text-editor or IDE to reformat the JSON data.要使其可读,请使用您的文本编辑器或IDE重新格式化 JSON 数据。

Sample output:样品 output:

dt : 1553709600
instant : 2019-03-27T18:00:00Z
zdt : 2019-03-27T13:00-05:00[America/Chicago]
main = {"temp":286.44,"temp_min":286.258,"grnd_level":1002.193,"temp_kf":0.18,"humidity":100,"pressure":1015.82,"sea_level":1015.82,"temp_max":286.44}
temp = 286.44
wind = {"deg":202.816,"speed":5.51}
speed = 5.51


dt : 1553713200
instant : 2019-03-27T19:00:00Z
zdt : 2019-03-27T14:00-05:00[America/Chicago]
main = {"temp":286.43,"temp_min":286.3,"grnd_level":1002.667,"temp_kf":0.13,"humidity":100,"pressure":1016.183,"sea_level":1016.183,"temp_max":286.43}
temp = 286.43
wind = {"deg":206.141,"speed":4.84}
speed = 4.84

You can serialize the response JSON string to POJOs by any one of the most popular JSON libraries such as Jackson or Gson , then retrieve fields you want of the object whose date field equals given date. You can serialize the response JSON string to POJOs by any one of the most popular JSON libraries such as Jackson or Gson , then retrieve fields you want of the object whose date field equals given date. BTW, your JSON string is invalid, ]} is missing at the end of it.顺便说一句,您的 JSON 字符串无效,末尾缺少]}

POJOs POJO

@JsonIgnoreProperties(ignoreUnknown = true)
class Response {
    List<Weather> list;

    //general getters and setters
}

@JsonIgnoreProperties(ignoreUnknown = true)
class Weather {
    JsonNode main;
    JsonNode wind;

    @JsonProperty("dt_txt")
    String dtTxt;

    //general getters and setters
}

Use @JsonIgnoreProperties (provided by Jackson) to ignore those fields you don't care while serialization.使用@JsonIgnoreProperties (由Jackson 提供)忽略序列化时您不关心的那些字段。

Code snippet代码片段

ObjectMapper mapper = new ObjectMapper();
Response response = mapper.readValue(jsonStr, Response.class);

String givenDate = "2019-11-21 12:00:00";
response.getList().forEach(e -> {
    if (givenDate.equals(e.getDtTxt())) {
        System.out.println("temp: " + e.getMain().get("temp").asText());
        System.out.println("wind speed:" + e.getWind().get("speed").asText());
    }
});

Console output控制台 output

temp: 282.2温度:282.2
wind speed:2.78风速:2.78

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

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