You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenWeatherMap API含方括号字段,Android Studio无法调用JSON数据求助

问题:OpenWeatherMap API字段带方括号无法调用,且仅部分区域可用

我正在开发一款Android天气应用,遇到两个棘手的问题:

  • OpenWeatherMap API返回的JSON数据里有被方括号包裹的字段,导致我在Android Studio里没法正常调用这些数据;
  • 这个API仅在部分区域能访问,我没法稳定测试。

目前我打算先通过Toast显示API返回的完整内容,确认数据能正常获取后再做后续开发,下面是我写的部分代码片段:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Retrofit初始化
        Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://api.openweathermap.org/data/2.5/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
        // 后续API请求代码还在完善中
    }
}

解决方案

1. 处理带方括号的JSON字段

首先要明确:JSON里的方括号代表数组/集合类型,不是普通的单个字段,所以不能用普通的对象类型去映射。举个例子,OpenWeatherMap的weather字段就是一个数组,返回格式大概是这样:

{"weather": [{"id": 800, "main": "Clear", "description": "clear sky"}]}

你需要在对应的实体类里用List来映射这个字段:

// 主响应实体类
public class WeatherResponse {
    // 用List<Weather>来接收数组类型的weather字段
    private List<Weather> weather;
    // 其他字段比如温度、湿度等
    private Main main;

    // 内部类对应数组里的单个对象
    public static class Weather {
        private int id;
        private String main;
        private String description;

        // 别忘了添加getter和setter方法
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        // 其他字段的getter/setter同理
    }

    public static class Main {
        private double temp;
        private int humidity;
        // getter/setter
    }

    // 主类的getter/setter
    public List<Weather> getWeather() { return weather; }
    public void setWeather(List<Weather> weather) { this.weather = weather; }
}

如果遇到个别字段被方括号包裹但实际是单个值的异常情况,先检查你的API请求参数是否正确(比如有没有误传数组类型的参数);如果确认是API返回的问题,可以用Gson的@SerializedName注解指定字段名,或者自定义类型转换器来处理。

2. 解决API仅部分区域可用的问题

  • 切换HTTPS协议:很多地区会限制HTTP的访问,把你的baseUrl改成HTTPS试试:https://api.openweathermap.org/data/2.5/
  • 配置代理(如果需要):如果是网络区域限制,可以给OkHttp添加代理配置,让请求通过代理访问:
// 初始化带代理的OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("你的代理地址", 代理端口)))
        .build();

// 把OkHttpClient传入Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.openweathermap.org/data/2.5/")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
  • 检查API Key有效性:确认你的API Key已经在OpenWeatherMap后台激活,并且没有设置访问白名单限制。

3. 用Toast验证API返回内容

你可以在Retrofit的回调里把返回的实体类转换成JSON字符串,然后用Toast显示,这样就能直观看到完整的返回内容:

// 先定义Retrofit接口
public interface WeatherApiService {
    @GET("weather")
    Call<WeatherResponse> getCurrentWeather(
            @Query("q") String cityName,
            @Query("appid") String apiKey,
            @Query("units") String units // 可选,比如传入"metric"获取摄氏度
    );
}

// 在MainActivity里发起请求并显示Toast
WeatherApiService apiService = retrofit.create(WeatherApiService.class);
Call<WeatherResponse> call = apiService.getCurrentWeather("Beijing", "你的API Key", "metric");

call.enqueue(new Callback<WeatherResponse>() {
    @Override
    public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) {
        if (response.isSuccessful() && response.body() != null) {
            // 把实体类转成JSON字符串
            String jsonContent = new Gson().toJson(response.body());
            Toast.makeText(MainActivity.this, jsonContent, Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(MainActivity.this, "请求失败:" + response.message(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onFailure(Call<WeatherResponse> call, Throwable t) {
        Toast.makeText(MainActivity.this, "网络错误:" + t.getMessage(), Toast.LENGTH_SHORT).show();
    }
});

内容的提问来源于stack exchange,提问作者user7405277

火山引擎 最新活动