You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 00:30:44