无法从OpenWeatherMap API获取JSON数据到Flutter应用(Curl可正常调用)
解决Flutter调用OpenWeatherMap API返回401错误的问题
用curl调用OpenWeatherMap API可正常获取数据,命令如下:
curl 'https://api.openweathermap.org/data/2.5/weather?lat={41.01}&lon={28.97}&appid={my_secret_api_key}'
OpenWeatherMap是免费服务,需验证邮箱后方可使用。
当前Flutter应用代码无法获取JSON数据,response.body返回401错误,暂未修改Album类,需先解决该问题:
import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; Future<Album> fetchAlbum() async { final response = await http.get( Uri.parse( 'https://api.openweathermap.org/data/2.5/weather?lat={41.01}&lon={28.97}&appid=${HttpHeaders.authorizationHeader}'), // Send authorization headers to the backend. headers: { HttpHeaders.authorizationHeader: '666319c58bc57caab32599c61b82c50e', }, ); print('response body: ${response.body}'); final responseJson = jsonDecode(response.body); return Album.fromJson(responseJson); } void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { late Future<Album> futureAlbum; @override void initState() { super.initState(); futureAlbum = fetchAlbum(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('Fetch Data Example'), ), body: Center( child: FutureBuilder<Album>( future: futureAlbum, builder: (context, snapshot) { if (snapshot.hasData) { return Text(snapshot.data!.title); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } // By default, show a loading spinner. return const CircularProgressIndicator(); }, ), ), ), ); } } //IGNORE THESE PLEASE, NOT IMPORTANT YET. SO I MOVED THEM HERE. class Album { final int userId; final int id; final String title; const Album({ required this.userId, required this.id, required this.title, }); factory Album.fromJson(Map<String, dynamic> json) { return Album( userId: json['userId'], id: json['id'], title: json['title'], ); } }
问题原因及修复方案
1. 核心错误点
OpenWeatherMap的API验证仅通过URL中的appid参数实现,你的代码存在两处关键错误:
- URL中
appid的值错误使用了${HttpHeaders.authorizationHeader},实际拼接后是字符串Authorization而非你的API密钥 - 额外添加了
Authorization请求头,这不是该API要求的验证方式
2. 修复后的fetchAlbum方法
Future<Album> fetchAlbum() async { const apiKey = '666319c58bc57caab32599c61b82c50e'; final response = await http.get( Uri.parse( 'https://api.openweathermap.org/data/2.5/weather?lat=41.01&lon=28.97&appid=$apiKey'), ); print('response body: ${response.body}'); final responseJson = jsonDecode(response.body); return Album.fromJson(responseJson); }
修复要点
- 直接在URL的
appid参数中填入真实API密钥,替换错误的HttpHeaders.authorizationHeader常量 - 移除多余的
headers参数,OpenWeatherMap不接受这种验证方式 - 移除经纬度参数外的
{},curl中的{}仅为占位符格式,实际请求需用真实数值
内容的提问来源于stack exchange,提问作者crag hack
相关产品推荐
相关产品推荐

