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

时间:2019-11-20 20:32:38

标签: java json android-studio parsing weather-api

我正在尝试使用Android Studio和Java构建一个简单的天气预报应用程序。我按照此处(https://www.androdocs.com/java/creating-an-android-weather-app-using-java.html)的说明进行操作并开始运行,并且可以正常运行。但是,我只能得到当前的天气。 Openweather Forecasting API调用似乎持续了5天。可以,但是如何获得用户指定的特定日期(在接下来的5天内)的天气-例如温度和风速?

下面是一个示例JSON响应(已缩短)。即使我可以在中午12点左右的某个特定日期提取信息,并获取该日期的温度和风速,也足够了。如何解析此JSON响应以获取特定日期的温度和风速?非常感谢...对不起,我是一个初学者...

  

{“ cod”:“ 200”,“消息”:0,“ cnt”:40,“列表”:[{“ dt”:1574283600,“ main”:{“ temp”:281.75,“ temp_min” :281.68,“温度最大值”:281.75,“压力”:995,“海平面”:995,“研磨水平”:980,“湿度”:93,“温度kf”:0.07},“天气”:[{“ id”: 501,“ main”:“ Rain”,“ description”:“中雨”,“ 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 ,“湿度”:91,“ temp_kf”:0.05},“天气”:[{“ id”:500,“主”:“雨”,“描述”:“小雨”,“图标”:“ 10n” }],“云”:{“全部”:100},“风”:{“速度”:5.55,“度”:140},“雨”:{“ 3h”:1.75},“系统”:{ “ pod”:“ n”},“ dt_txt”:“ 2019-11-21 00:00:00”},{“ dt”:1574305200,“ main”:{“ temp”:279.48,“ temp_min”:279.44 ,“温度最大值”:279.48,“压力”:994,“海平面”:994,“研磨水平”:980,“湿度”:95,“温度kf”:0.04},“天气”:[{“ id”:500, “ main”:“ Rain”,“ description”:“ light rain”,“ icon”:“ 10n”}],“ clouds”:{“ all”:10 0},“ 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 ,“海平面”:995,“地平面”:980,“湿度”:94,“温度kf”:0.02},“天气”:[{“ id”:500,“主”:“雨”,“描述”: “小雨”,“图标”:“ 10n”}],“云”:{“全部”:100},“风”:{“速度”:1.73,“度”:128},“雨”:{ “ 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,“海平面”:995,“ grnd_level”:981,“湿度”:95,“ temp_kf”:0}, “天气”:[{“ id”:804,“主要”:“云”,“描述”:“阴云”,“图标”:“ 04d”}],“云”:{“所有”: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},”天气“:[{” id“:500,”主要“:”雨“,”描述“:”小雨“,” icon“:” 10d“}],”云“:{”所有“:100},”风“:{”速度“:2.78,”度“:129},”雨“:{” 3h“ :0.19},“ sys”:{“ pod”:“ d”},“ dt_txt”:“ 2019-11-21 12:00:00”}

2 个答案:

答案 0 :(得分:1)

您可以使用JacksonGson之类的任何最受欢迎的JSON库将响应JSON字符串序列化为POJO,然后检索日期字段等于给定日期的对象所需的字段。顺便说一句,您的JSON字符串无效,它的末尾缺少]}

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
}

使用@JsonIgnoreProperties(由Jackson提供)忽略序列化时不需要的那些字段。

代码段

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

控制台输出

  

温度:282.2
  风速:2.78

答案 1 :(得分:1)

JSON-简单

这里是一个示例应用程序,它使用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();
        }
    }
}

小数点分隔符

请注意,遇到缺少小数点分隔符的风速数据点时,此代码会炸毁。为了保持一致性,该数据的发布者应在编写,例如,1.0而不是1。如果他们这样做,则库将把1.0解析为Double,而不是将1解析为Long

JSON-Simple 1 现在已消失

此代码还使用JSON-Simple的原始版本1,现已不存在。该项目是分叉的,产生了截然不同的版本2和3。

有关解析十进制问题和指向Parsing decimal numbers, some of which lack a decimal separator, in JSON data using JSON-Simple (Java)的链接的详细信息,请参见此页面forked project

非用于生产用途

因此,尽管我不建议将此代码用于生产,但它可能会一直为您提供帮助。为了进行实际工作,请考虑JSON-Simple的更高版本3或可用于Java的其他几个JSON处理库中的任何一个。

请参见this URL上的示例数据。要使其可读,请使用文本编辑器或IDE重新格式化JSON数据。

示例输出:

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