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

Flutter(Dart)中使用类无法从JSON获取数据问题求助

问题:用生成的Dart类解析天气API数据时,temperature字段返回null

成功获取weatherstack API的完整JSON响应,但通过生成的Current类访问temperature时输出null。

代码示例

获取数据的方法:

Future<Current> getweatherData({required String location}) async {
  final _response = await http.get(Uri.parse(
      'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location'));
  print(_response.body); // 打印API响应
  final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>;
  final _data = Current.fromJson(_bodyJson);
  print(_data.temperature); // 输出null
  return _data;
}

生成的Current类:

import 'package:json_annotation/json_annotation.dart';

part 'current.g.dart';

@JsonSerializable()
class Current {
  @JsonKey(name: 'observation_time')
  String? observationTime;
  int? temperature;
  @JsonKey(name: 'weather_code')
  int? weatherCode;
  @JsonKey(name: 'weather_icons')
  List<String>? weatherIcons;
  @JsonKey(name: 'weather_descriptions')
  List<String>? weatherDescriptions;
  @JsonKey(name: 'wind_speed')
  int? windSpeed;
  @JsonKey(name: 'wind_degree')
  int? windDegree;
  @JsonKey(name: 'wind_dir')
  String? windDir;
  int? pressure;
  int? precip;
  int? humidity;
  int? cloudcover;
  int? feelslike;
  @JsonKey(name: 'uv_index')
  int? uvIndex;
  int? visibility;
  @JsonKey(name: 'is_day')
  String? isDay;

  Current({
    this.observationTime,
    this.temperature,
    this.weatherCode,
    this.weatherIcons,
    this.weatherDescriptions,
    this.windSpeed,
    this.windDegree,
    this.windDir,
    this.pressure,
    this.precip,
    this.humidity,
    this.cloudcover,
    this.feelslike,
    this.uvIndex,
    this.visibility,
    this.isDay,
  });

  factory Current.fromJson(Map<String, dynamic> json) {
    return _$CurrentFromJson(json);
  }

  Map<String, dynamic> toJson() => _$CurrentToJson(this);
}

问题原因

weatherstack的API响应是嵌套结构,所有天气数据都在顶层的current字段中,响应大致结构如下:

{
  "request": {...},
  "location": {...},
  "current": {
    "temperature": 22,
    "observation_time": "09:45 AM",
    ...
  }
}

你直接把整个顶层JSON Map传给Current.fromJson,但Current类的字段对应是current子Map里的键,自然匹配不到,所以temperature返回null。

解决方案

方法1:直接提取current子Map解析

修改获取数据的代码,先从顶层Map中取出current对应的子Map,再传给Current.fromJson:

Future<Current> getweatherData({required String location}) async {
  final _response = await http.get(Uri.parse(
      'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location'));
  print(_response.body);
  final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>;
  // 提取current子Map
  final _currentJson = _bodyJson['current'] as Map<String, dynamic>;
  final _data = Current.fromJson(_currentJson);
  print(_data.temperature); // 现在能正确输出温度值
  return _data;
}

方法2:生成完整的响应类(推荐)

如果需要用到request、location等其他字段,可以生成包含整个响应结构的类:

import 'package:json_annotation/json_annotation.dart';
import 'current.dart';

part 'weather_response.g.dart';

@JsonSerializable()
class WeatherResponse {
  Map<String, dynamic>? request;
  Map<String, dynamic>? location;
  Current? current;

  WeatherResponse({this.request, this.location, this.current});

  factory WeatherResponse.fromJson(Map<String, dynamic> json) =>
      _$WeatherResponseFromJson(json);

  Map<String, dynamic> toJson() => _$WeatherResponseToJson(this);
}

然后修改获取数据的代码:

Future<Current> getweatherData({required String location}) async {
  final _response = await http.get(Uri.parse(
      'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location'));
  print(_response.body);
  final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>;
  final _weatherResponse = WeatherResponse.fromJson(_bodyJson);
  print(_weatherResponse.current?.temperature); // 正确输出温度
  return _weatherResponse.current!;
}

记得运行flutter pub run build_runner build生成对应的.g.dart文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:14:58